Releases: objectstack-ai/framework
Release list
objectstack-vscode@12.0.0
objectstack-vscode@12.0.0
create-objectstack@12.0.0
create-objectstack@12.0.0
@objectstack/verify@12.0.0
Patch Changes
-
7c09621: feat(security)!:
api.requireAuthnow defaults totrue— anonymous access to the data API is denied by default (ADR-0056 D2 flip)BREAKING. The global
requireAuthdefault flipped FROMfalseTOtrue
(RestApiConfigSchema.requireAuthin@objectstack/spec, mirrored by
RestServer.normalizeConfigin@objectstack/rest). Anonymous requests to
the/data/*CRUD + batch endpoints are now rejected with HTTP 401 unless the
deployment explicitly opts out. (Scope note: this gate covers the REST
/data/*surface — the metadata read/write endpoints and the dispatcher
GraphQL route have their own pre-existing anonymous posture, tracked
separately; this flip does not change them.)Migration (one line): a deployment that intentionally serves data publicly
(demo / playground / kiosk) sets the flag on the stack config — now a declared
ObjectStackDefinitionSchema.apifield, so it survivesdefineStackstrict
parsing (previously an undeclared top-levelapikey was silently stripped):export default defineStack({ // … api: { requireAuth: false }, });
The REST plugin logs a boot warning for the explicit opt-out so a fail-open
posture is always visible. A misplacedapi.requireAuthat the plugin level
(one nesting short) is now also called out with a boot warning instead of
being silently ignored.What keeps working with no action:
- Share links — validate their token, then read under a system context.
- Public forms — self-authorizing via the declaration-derived
publicFormGrant(create + read-back on the declared target object only);
noguest_portalprofile needed. - Control plane —
/auth,/health,/discoveryare exempt. objectstack servewith an auth-less stack — the CLI passes an explicit
requireAuth: falsefor stacks whose tier set has noauth(nothing could
authenticate against them), with the boot warning.
-
Updated dependencies [a8df396]
-
Updated dependencies [e695fe0]
-
Updated dependencies [07f055c]
-
Updated dependencies [1b1b34e]
-
Updated dependencies [9796e7c]
-
Updated dependencies [f84f8d5]
-
Updated dependencies [9693a36]
-
Updated dependencies [ffafb30]
-
Updated dependencies [7c09621]
-
Updated dependencies [2d567cb]
-
Updated dependencies [e3498fb]
-
Updated dependencies [24b62ee]
-
Updated dependencies [7709db4]
-
Updated dependencies [48ad533]
-
Updated dependencies [2082109]
-
Updated dependencies [7c09621]
-
Updated dependencies [c2fdbf9]
-
Updated dependencies [9860de4]
-
Updated dependencies [069c205]
- @objectstack/spec@12.0.0
- @objectstack/plugin-auth@12.0.0
- @objectstack/plugin-security@12.0.0
- @objectstack/service-automation@12.0.0
- @objectstack/runtime@12.0.0
- @objectstack/objectql@12.0.0
- @objectstack/rest@12.0.0
- @objectstack/core@12.0.0
- @objectstack/driver-sqlite-wasm@12.0.0
- @objectstack/plugin-hono-server@12.0.0
- @objectstack/plugin-org-scoping@12.0.0
- @objectstack/plugin-sharing@12.0.0
- @objectstack/service-analytics@12.0.0
- @objectstack/service-datasource@12.0.0
- @objectstack/service-settings@12.0.0
@objectstack/types@12.0.0
@objectstack/trigger-schedule@12.0.0
Patch Changes
@objectstack/trigger-record-change@12.0.0
Patch Changes
@objectstack/trigger-api@12.0.0
Patch Changes
@objectstack/studio@12.0.0
Patch Changes
- Updated dependencies [a8df396]
- Updated dependencies [e695fe0]
- Updated dependencies [07f055c]
- Updated dependencies [7c09621]
- Updated dependencies [7709db4]
- Updated dependencies [2082109]
- Updated dependencies [7c09621]
- Updated dependencies [9860de4]
- Updated dependencies [069c205]
- @objectstack/spec@12.0.0
- @objectstack/platform-objects@12.0.0
@objectstack/spec@12.0.0
Major Changes
-
7c09621: feat(security)!:
api.requireAuthnow defaults totrue— anonymous access to the data API is denied by default (ADR-0056 D2 flip)BREAKING. The global
requireAuthdefault flipped FROMfalseTOtrue
(RestApiConfigSchema.requireAuthin@objectstack/spec, mirrored by
RestServer.normalizeConfigin@objectstack/rest). Anonymous requests to
the/data/*CRUD + batch endpoints are now rejected with HTTP 401 unless the
deployment explicitly opts out. (Scope note: this gate covers the REST
/data/*surface — the metadata read/write endpoints and the dispatcher
GraphQL route have their own pre-existing anonymous posture, tracked
separately; this flip does not change them.)Migration (one line): a deployment that intentionally serves data publicly
(demo / playground / kiosk) sets the flag on the stack config — now a declared
ObjectStackDefinitionSchema.apifield, so it survivesdefineStackstrict
parsing (previously an undeclared top-levelapikey was silently stripped):export default defineStack({ // … api: { requireAuth: false }, });
The REST plugin logs a boot warning for the explicit opt-out so a fail-open
posture is always visible. A misplacedapi.requireAuthat the plugin level
(one nesting short) is now also called out with a boot warning instead of
being silently ignored.What keeps working with no action:
- Share links — validate their token, then read under a system context.
- Public forms — self-authorizing via the declaration-derived
publicFormGrant(create + read-back on the declared target object only);
noguest_portalprofile needed. - Control plane —
/auth,/health,/discoveryare exempt. objectstack servewith an auth-less stack — the CLI passes an explicit
requireAuth: falsefor stacks whose tier set has noauth(nothing could
authenticate against them), with the boot warning.
Minor Changes
-
a8df396: feat(spec,lint): adaptive record surface + semantic field
spanfor field-heavy objects (#2578)Field-heavy objects need two things the protocol did not express well: multi-column
forms, and opening create/edit/detail as a full page rather than a cramped popup —
for some objects, automatically. Because all metadata is AI-authored, the design
goal is to make AI unable to get it wrong, which reshaped both features away from
new authored keys.deriveRecordSurface(new spec derivation, ADR-0085 §5). A record's default
surface — fullpagevsdrawer/modaloverlay — is derived from how heavy the
record is (visible, non-system field count; mobile always pages), not authored. Per
ADR-0085 §2's admission test arecordSurfaceobject key would fail: field count is
exactly the kind of fact a machine can infer, and modal-vs-page is pure
re-arrangement, not a business fact. So there is no new object key and no new
ADR — just a single shared derivation renderers consume as a default (an explicit
form/navigation config still wins), plus a one-line clarification to ADR-0085 §2's
rejected-keys list sorecordSurfaceis not re-proposed. Explicit per-object control
remains the sanctioned assigned-page path.FormField.span: 'auto' | 'full'(new, replaces absolutecolSpanas the
primary primitive). Under a per-surface derived column count (mobile 1 / modal 2 /
page 3-4) an absolutecolSpan: 3only lines up at the one width the author
imagined — fragile by construction. The relativespanis decoupled from the column
count:auto(default; omit it) sizes by widget type × current columns,fulltakes
the whole row at any count.colSpanis retained for back-compat and clamped by the
renderer;halfwas considered and deferred (weakest AI-safety). The rationale lives
here rather than in a new ADR, per the fewer-ADRs convention.validateFormLayout(new lint, ADR-0078/0019). Two advisory rules over authored
form views:form-field-unknown(a section references a field not on the bound
object — silently never renders) andabsolute-colspan-discouraged(steers authors
tospan: 'full'). Both warnings, with fix hints, held to the same bar for AI and
hand authors.NavigationConfig.size(new) replaces pixelwidth. A T-shirt bucket
(auto/sm/md/lg/xl/full, defaultauto, aligned withFormView.modalSize) for a
drawer/modal detail overlay.width/drawerWidth(pixel) are deprecated: a pixel
width cannot be authored blind — the author (often an AI) does not know the client
viewport.automeans the renderer derives the size from field count and clamps to
the viewport, so AI writes nothing.All additive: no exports removed, no behavior change for existing metadata.
-
e695fe0: feat(spec,lint): reject userFilters on object list views (ADR-0053 phase 4)
ADR-0053 reserves
userFilters/quickFiltersfor page lists ("filters" mode);
on an object list view ("views" mode — where theViewTabBaris the only nav
control) they are silently dropped. This lands the phase-4 guardrail as a
layered defence, so the wrong-context authoring mistake is caught without
breaking existing metadata:- Type-level (author time): new
ObjectListViewSchema=ListViewSchema
minususerFilters. Object built-inlistViewsanddefineView
list/listViewsnow use it, souserFilterson an object list view is a
tscerror. The fullListViewSchema(page "filters" mode) is untouched. - Runtime (back-compat): the field is STRIPPED at parse (default strip, no
throw), so existing metadata keeps loading —ObjectSchema.parsenever fails
on a strayuserFilters. - Author/CI (actionable): new
@objectstack/lintrule
validateListViewMode, wired intoos validate, reports the wrong-context
field PRE-parse (before the schema strips it) with a fix hint.
Closes the schema half of objectui #2219; supersedes the interim runtime warn in
objectui #2220. - Type-level (author time): new
-
7709db4: feat(security): permission-set package provenance + declared-permission seeding (ADR-0086 P1)
Packages now ship working default access for their own objects, with a
machine-checkable metadata↔config boundary:- Spec (ADR-0086 D3):
PermissionSetSchema.packageId(owning package for
a package-shipped set; absent = env-authored) and per-record provenance
managedBy: 'package' | 'platform' | 'user'on the existing
metadata-persistence axis. Persisted onsys_permission_setas
package_id/managed_by(new columns +package_idindex). - Seeding (ADR-0086 D5): new
bootstrapDeclaredPermissions— the sibling
ofbootstrapDeclaredRoles— materializesstack.permissionsinto
sys_permission_setat boot withmanaged_by:'package'+package_id.
Idempotent and upgrade-aware: rows the seeder owns are re-seeded to the
shipped declaration on every boot; rows owned by a different package are
refused loudly; env-authoredplatform/user/legacy rows are never
clobbered. Closes the ADR-0078 inert-metadata violation for
stack.permissions(declared sets were runtime-enforced but never
materialized — invisible to the admin surface, uninstall undefined). - Conformance matrix row
declarative-permission-seeding(ADR-0056 D10) +
dogfood proof pin the behavior so it cannot regress to inert.
- Spec (ADR-0086 D3):
-
2082109: Detail-page related lists:
relatedList: 'primary'prominence + optional related-list columns (#2579).Field.relatedListon a child'slookup/master_detailFK becomes a tri-state
boolean | 'primary'.'primary'marks a CORE relationship — a prominence hint
(ADR-0085), not a layout switch — that the detail page promotes to its own tab,
while non-primary children collapse into a single shared "Related" tab.
false/truekeep their meaning (suppress / show in the derived default), so
the change is additive and opt-in per relationship (no primary anywhere → the
detail page is byte-for-byte the legacy stacked default).RecordRelatedListProps.columnsbecomes optional: when omitted the related list
derives its columns from the child object'shighlightFields/ default list
columns — a related list is just another surface that lists that object.
Required → optional is back-compat.Renderer + derivation changes ship in objectui:
relatedList: 'primary'→ own
tab; one related list per eligible FK (a child that references the parent
through several relationships now surfaces each, previously only the first);
self-referential relationships (hierarchies) surface a "child" list; and the
lookup-picker default columns are unified onto the samehighlightFields
source so a picker and a related list of the same object agree with zero
per-surface config. -
069c205: Add a build-time view-reference lint that fails
os compileon a broken form-view reference, and surfaces the previously-silent_2rename collision as a warning (#2554).expandViewContainergains a behaviour-preserving companionexpandViewContainerWithDiagnosticsthat also reports every<object>.<key>name collision. List and form views share one namespace during expansion, and the defaultlistimplicitly claims<object>.default; a colliding key was previously renamed to<object>.<key>_2silently, so references (form actiontargets, navigationviewNames) resolved to the other view.The new
lint-view-refsbuild lint consumes those diagnostics with a broken/fragile severity split, tuned so an upgrade does NOT break existing apps that merely have a colliding key:- view-ref-form-target-kind — ERROR (fails the build): a
type:'form'action whosetargetresolves to an existing LIST view — the concrete #2554 breakage (a blank form, a silently no-op submit). High-confidence, so it fails. - view-key-collision...
- view-ref-form-target-kind — ERROR (fails the build): a
@objectstack/setup@12.0.0
Patch Changes
- Updated dependencies [a8df396]
- Updated dependencies [e695fe0]
- Updated dependencies [07f055c]
- Updated dependencies [7c09621]
- Updated dependencies [7709db4]
- Updated dependencies [2082109]
- Updated dependencies [7c09621]
- Updated dependencies [9860de4]
- Updated dependencies [069c205]
- @objectstack/spec@12.0.0
- @objectstack/platform-objects@12.0.0