Skip to content

Commit 346c8a6

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/issue-4352-action-body-type-gate
2 parents d9c4f0d + 21676eb commit 346c8a6

35 files changed

Lines changed: 716 additions & 983 deletions
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
"@objectstack/spec": minor
3+
"@objectstack/service-datasource": minor
4+
---
5+
6+
feat(spec,service-datasource): graduate the driver factory's four legacy `datasource.config` `??` fallbacks into an ADR-0087 conversion (#4456)
7+
8+
`createDefaultDatasourceDriverFactory` still carried four undeclared read-side
9+
`??` fallbacks that predate the #4410 config gate: sqlite `file`/`database`
10+
(canonical `filename`), postgres/mysql `connectionString` (canonical `url`),
11+
postgres/mysql/mongo `user` (canonical `username`), and mongo `uri` (canonical
12+
`url`). They were never part of the contract — no schema, form, doc or example
13+
ever named them — and they kept working only because the reader was lenient
14+
(AGENTS.md Prime Directive #12 debt).
15+
16+
**FROM → TO, applied automatically at load** by the new conversion entry
17+
`datasource-config-driver-key-aliases` (retired-from-load-path; replayed over
18+
stored `sys_metadata` rows by `applyConversionsToStoredItem` and by
19+
`os migrate meta`):
20+
21+
- sqlite / sqlite-wasm: `config.file` / `config.database``config.filename`
22+
- postgres / mysql: `config.connectionString``config.url`, `config.user``config.username`
23+
- mongo: `config.uri``config.url`, `config.user``config.username`
24+
25+
The mapping is driver-aware — `database` renames only under sqlite, where it
26+
aliased the file path; for postgres/mysql/mongo it is a canonical key and is
27+
untouched. A canonical key already present wins; the legacy alias is left
28+
shadowed (the factory's `??` precedence, preserved).
29+
30+
**Behaviour change (the deletion):** the factory now reads exactly one spelling
31+
per key. A `DatasourceConnectionSpec` handed to the factory *directly* with a
32+
legacy spelling is no longer honoured — authored metadata was already rejected
33+
by the per-driver zod gate with a rename hint (#4410), and stored runtime
34+
datasource rows are canonicalized at every rehydration seam (including the
35+
`sys_metadata` restore path in `DatasourceAdminServicePlugin`, which now
36+
replays the full conversion chain), so no supported path still produces the
37+
legacy shape. One-line fix for hand-built specs: use the canonical key from
38+
the table above.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
"@objectstack/spec": major
3+
---
4+
5+
feat(spec)!: the notification vocabulary has one owner per name — `@objectstack/spec/ui` no longer exports `Notification(Schema)` / `NotificationConfig(Schema)`, and `@objectstack/spec/system` no longer exports `NotificationConfig(Schema)` (#4610)
6+
7+
The names `Notification` / `NotificationSchema` (`./api` vs `./ui`) and
8+
`NotificationConfig` / `NotificationConfigSchema` (`./system` vs `./ui`)
9+
each resolved to **two different declarations** depending on the import
10+
path — the #4411 dual-source trap. Resolution (three-repo,
11+
import-statement-level consumer scan: framework, cloud, objectui):
12+
13+
- **Removed** `NotificationSchema` / `Notification` from
14+
`@objectstack/spec/ui`. This was a toast/banner "notification instance"
15+
shape (`type`/`severity`/`message`/`duration`/`actions`/`position` + ARIA
16+
props) with **zero importers** in all three repos — objectui's toaster
17+
never adopted it. The live contract is `./api`'s `Notification(Schema)`:
18+
the REST inbox row (`id`/`type`/`title`/`body`/`read`/`data`/`actionUrl`/
19+
`createdAt`) embedded in `ListNotificationsResponseSchema`, served by
20+
`/api/v1/notifications`, implemented by `@objectstack/client`, and
21+
mirrored by `InboxNotification` in `@objectstack/spec/contracts`
22+
(ADR-0030: the bell reads this shape).
23+
- FROM `import { NotificationSchema, type Notification } from '@objectstack/spec/ui'`
24+
TO `import { NotificationSchema, type Notification } from '@objectstack/spec/api'`.
25+
**Shape change**: the api row is an inbox record, not a presentation
26+
config — the ui shape's `severity` / `duration` / `dismissible` /
27+
`actions` / `position` / ARIA fields do not exist there. For the
28+
presentation vocabulary keep using the ui enums, which are unchanged:
29+
`NotificationTypeSchema`, `NotificationSeveritySchema`,
30+
`NotificationPositionSchema`, `NotificationActionSchema` (+ their
31+
types) still live in `@objectstack/spec/ui`.
32+
- **Removed** `NotificationConfigSchema` / `NotificationConfig` from **both**
33+
`@objectstack/spec/system` and `@objectstack/spec/ui` — the bare name left
34+
the spec export surface entirely. Both declarations had zero importers in
35+
all three repos and were wired into no parent schema. The system side (a
36+
channel + template + recipients + schedule + retryPolicy + tracking
37+
"unified notification management protocol") predates ADR-0030's accepted
38+
delivery architecture and advertised capability the runtime does not
39+
deliver (its channel enum's `push`/`slack`/`teams`/`webhook` dead-letter,
40+
#3197; nothing reads `schedule`/`retryPolicy`/`tracking`). The ui side (a
41+
toaster global config: `defaultPosition`/`defaultDuration`/`maxVisible`/
42+
`stackDirection`/`pauseOnHover`) was never adopted by objectui.
43+
- FROM `import { NotificationConfigSchema } from '@objectstack/spec/system'` (or `.../ui`) →
44+
TO: no direct replacement. The live delivery vocabulary is
45+
`NotificationService.emit` (`INotificationService`,
46+
`@objectstack/spec/contracts`), the `notify` flow node
47+
(`NotifyConfigSchema`, `@objectstack/spec/automation`) and the
48+
`sys_notification*` platform objects; per-user delivery preferences are
49+
`NotificationPreferences(Schema)` in `@objectstack/spec/api`.
50+
- `@objectstack/spec/api`'s `Notification(Schema)` and
51+
`NotificationPreferences(Schema)` are **unchanged**; `./api` is now the
52+
sole owner of the bare `Notification(Schema)` names. Imports from `./api`
53+
need no migration. `@objectstack/spec/system`'s `NotificationChannel(Schema)`,
54+
`EmailTemplate(Schema)`, `SMSTemplate(Schema)`, `PushNotification(Schema)`
55+
and `InAppNotification(Schema)` are **unchanged**.
56+
57+
`dual-source-exports.baseline.json` shrinks by exactly these 4 rows (28 → 24,
58+
#4535 C3).
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
"@objectstack/spec": major
3+
---
4+
5+
Resolve the `Session` dual source — `./api` keeps the bare names, the `./identity` declaration is removed (#4641)
6+
7+
`Session` and `SessionSchema` were each declared **twice**, once on
8+
`@objectstack/spec/api` and once on `@objectstack/spec/identity`. Which shape a
9+
consumer got depended only on which entry point they imported from — the #4411
10+
trap — and the two did not even agree on field names, so the mistake surfaced as
11+
a runtime `undefined`, not a type error.
12+
13+
**FROM → TO**
14+
15+
| Import | Before | After |
16+
|:--|:--|:--|
17+
| `@objectstack/spec/api` | `Session` / `SessionSchema` | unchanged — this is now the only declaration |
18+
| `@objectstack/spec/identity` | `Session` / `SessionSchema` (a second, different shape) | **removed** |
19+
20+
The surviving `./api` shape is the wire contract:
21+
22+
```ts
23+
{ id: string; expiresAt: string; token?: string; ipAddress?: string; userAgent?: string; userId: string }
24+
```
25+
26+
It is embedded in `SessionResponseSchema`, the body served for
27+
`AuthEndpointPaths.getSession` (`/get-session`, `/me`, `/refresh`).
28+
29+
The removed `./identity` shape was
30+
`{ id, sessionToken, userId, activeOrganizationId?, expires, createdAt, updatedAt, ipAddress?, userAgent?, fingerprint? }`.
31+
32+
**Nothing consumes it.** An import-statement-level scan across framework, `cloud`
33+
and `objectui` found no importer outside its own unit test, and it was wired into
34+
no parent schema. It had also drifted from the record it claimed to describe: the
35+
**enforced** session row is the `sys_session` object in
36+
`@objectstack/platform-objects`, which spells the columns `token` and
37+
`expires_at` (matching `./api`, not `./identity`) and has no `fingerprint` at all.
38+
39+
**If you were importing `Session` from `@objectstack/spec/identity`**, change the
40+
specifier to `@objectstack/spec/api` and rename the fields you read:
41+
`sessionToken``token`, `expires``expiresAt`. `createdAt` / `updatedAt` /
42+
`activeOrganizationId` / `fingerprint` are not on the wire shape — read the
43+
persisted record through the `sys_session` object, which is what the migration
44+
and the auth plugin actually enforce.
45+
46+
Reference docs follow the declaration: `Session` is now documented on the
47+
`references/api/auth` page (the module that declares it) instead of the
48+
name-collision page `references/api/identity`, which is removed.

content/docs/references/api/auth.mdx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ and Access Control.
1818
## TypeScript Usage
1919

2020
```typescript
21-
import { AuthProvider, LoginRequestSchema, LoginType, RefreshTokenRequestSchema, RegisterRequestSchema, SessionResponseSchema, SessionUserSchema, UserProfileResponseSchema } from '@objectstack/spec/api';
22-
import type { AuthProvider, LoginRequest, LoginType, RefreshTokenRequest, RegisterRequest, SessionResponse, SessionUser, UserProfileResponse } from '@objectstack/spec/api';
21+
import { AuthProvider, LoginRequestSchema, LoginType, RefreshTokenRequestSchema, RegisterRequestSchema, SessionSchema, SessionResponseSchema, SessionUserSchema, UserProfileResponseSchema } from '@objectstack/spec/api';
22+
import type { AuthProvider, LoginRequest, LoginType, RefreshTokenRequest, RegisterRequest, Session, SessionResponse, SessionUser, UserProfileResponse } from '@objectstack/spec/api';
2323

2424
// Validate data
2525
const result = AuthProvider.parse(data);
@@ -93,6 +93,22 @@ const result = AuthProvider.parse(data);
9393
| **image** | `string` | optional | |
9494

9595

96+
---
97+
98+
## Session
99+
100+
### Properties
101+
102+
| Property | Type | Required | Description |
103+
| :--- | :--- | :--- | :--- |
104+
| **id** | `string` || |
105+
| **expiresAt** | `string` || |
106+
| **token** | `string` | optional | |
107+
| **ipAddress** | `string` | optional | |
108+
| **userAgent** | `string` | optional | |
109+
| **userId** | `string` || |
110+
111+
96112
---
97113

98114
## SessionResponse

content/docs/references/api/identity.mdx

Lines changed: 0 additions & 35 deletions
This file was deleted.

content/docs/references/api/meta.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@
3030
"core-services",
3131
"events",
3232
"export",
33-
"identity",
3433
"metadata",
35-
"notification",
3634
"package-api",
3735
"package-registry",
3836
"plugin-rest-api",

content/docs/references/api/notification.mdx

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)