-
22013aa: Split the overloaded
managedBy: 'system'bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220). Thesystembucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row asbetter-auth/append-onlybut, unlikebetter-auth, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap).Rather than add a new
managedByenum value (which would fall through to fully-editableplatformdefaults on already-deployed Console clients), the write policy is now the resolved affordance (resolveCrudAffordances= bucket default +userActions), and engine-owned is defined as asystem/append-onlyobject that grants no write:- Writable set declares
userActions— the RBAC link tables (sys_user_position,sys_user_permission_set,sys_position_permission_set),sys_user_preference,sys_approval_delegation, and the messaging config grids (sys_notification_preference/…_subscription/…_template) now declareuserActions: { create, edit, delete: true }. The affordance is a declaration only — theDelegatedAdminGate/ RLS / permission sets remain the authz. - Engine-owned objects locked to reads —
apiMethods: ['get','list']added where absent (jobs, notifications, approval request/approver/token/action,sys_record_share,sys_automation_run, mail/settings/secret audit, the messaging delivery pipeline).sys_secretis explicitly read-locked (an emptyapiMethodsarray fails open). sys_import_jobstays engine-owned: the REST import route now writes its job rowsisSystem-elevated (attribution preserved via the explicitcreated_bystamp) and the object is locked to['get','list'].- New engine write guard (
assertEngineOwnedWriteAllowed, plugin-security) fail-closed rejects user-context generic writes to engine-ownedsystem/append-onlyobjects, keyed off the resolved affordance;isSystemand context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. reconcileManagedApiMethods(objectql registry) now runs for every managed bucket, not justbetter-auth: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049)./me/permissionsclamp (plugin-hono-server) now clampssystem/append-onlyas well asbetter-auth, so the client hint reflectspermission ∩ guard.
Potentially breaking: a downstream/third-party
systemobject that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. DeclareuserActionsopening the verbs the object legitimately takes from a user context.better-authkeeps plugin-auth's identity write guard unchanged; the row-levelmanaged_byprovenance vocabulary (ADR-0066) is a different axis and is untouched. - Writable set declares
-
bfa3c3f: Broadcast a
transactionalBatchcapability bit in discovery so clients negotiate the atomic cross-object batch declaratively, instead of runtime-probing 404/405/501 (#3298).The atomic cross-object batch endpoint (
POST {basePath}/batch, #1604 / ADR-0034 item 4) and its typed SDK surface (client.data.batchTransaction, #3271) already shipped, but discovery never told a client whether a backend actually supports it. Consumers (notably ObjectUI'sObjectStackAdapter) had to probe: fire a/batch, read404/405(no route) or501(no runtime transaction), and only then fall back to non-atomic client-side simulation. That is "find out by calling", not capability negotiation — it cannot be decided at connect time and cannot serve as the "minimum backend supports/batch" gate that blocks hard-deleting the non-atomic fallback downstream.WellKnownCapabilitiesSchemagains a requiredtransactionalBatch: boolean, and every discovery producer fills it honestly (declared === enforced), so it never becomes a declared-but-unpopulated bit:@objectstack/metadata-protocol(getDiscovery) — reports whether the runtime engine can honour a transaction (typeof engine.transaction === 'function'). The/batchhandler runs its ops insideengine.transaction(), which degrades to a non-atomic passthrough (or 501) without one.@objectstack/rest(/discovery) — ANDs the engine signal with whether it actually mounts the route (api.enableBatch), so a server with batch disabled reportsfalseeven on a transaction-capable engine (never advertise an endpoint that would 404).@objectstack/plugin-hono-server(standalone discovery) — reportsfalse: this minimal surface registers CRUD only and does not mount/batch(that ships with@objectstack/rest). Under-reporting is the safe direction — a client keeps its correct-but-slower fallback rather than losing atomicity.@objectstack/client— already normalizes hierarchicalcapabilitiesto flat booleans, soclient.capabilities.transactionalBatchis exposed (and now typed) for declarative consumers.
The bit follows the existing capability semantics:
true⟺ the/batchroute is mounted and the runtime can honour a transaction — the exact condition under which the endpoint returns200rather than404/405/501. Additive and behavior-preserving; only the discovery payload gains a field. -
62a2117: Split the overloaded
managedBy: 'system'bucket with an explicitengine-ownedvalue (ADR-0103 addendum, #3343). ADR-0103 deferred the enum split ("revisitable later as a rename") because a newmanagedByvalue would fall through to the fully-editableplatformdefault on deployed Console clients. Both reasons against it are now retired — the server-side write guard /apiMethodsreconciliation //me/permissionsclamp make that fallthrough cosmetic (the write is rejected regardless of what the client renders), and objectui#2712 closed the UI union — so v16 lands it, additively.- New enum value
engine-ownedwith the same all-locked default affordance row assystem(create/import/edit/delete: false,exportCsv: true). It joinsENGINE_OWNED_BUCKETS(the engine write guard) andGUARDED_WRITE_BUCKETS(the/me/permissionsclamp); the guard,reconcileManagedApiMethods, and the clamp mechanisms are unchanged —engine-ownedis an explicit member of the set they already covered by resolved affordance. - 20 objects relabelled
system → engine-owned— the ones the engine owns end to end and that declared no write-openinguserActions(the metadata store, jobs, approval runtime rows, sharing rows,sys_automation_run, the messaging delivery/receipt pipeline,sys_secret, settings). One-line, behaviour-identical per object. - 8 admin/user-writable objects keep
managedBy: 'system'(the RBAC link tables,sys_user_preference,sys_approval_delegation, the messaging config grids) —systemnow reads as "engine-managed schema, writable viauserActions".
Behaviour-, enforcement- and wire-identical: resolved affordances, the guard verdict, the 405
apiMethodsreconciliation, and the permissions clamp are the same before and after — this is a self-documenting relabel, not a policy change. No data migration (managedByis schema metadata) and no code branches on the'system'literal. Retiring the overloadedsystementirely (moving the 8 writable objects to a dedicated bucket) is a breaking rename deferred to v17. - New enum value
-
efbcfe1: feat(observability): admin-only richer per-request timing detail via
X-OS-Debug-Timing: json(#2408)Completes the optional "richer JSON" diagnostic from #2408. In addition to the basic
Server-Timingheader, an admin/service caller can now request a per-query breakdown — the slowest SQL statements and a query count — by sendingX-OS-Debug-Timing: json. The detail is returned in a separateX-OS-Debug-Timing-Detailresponse header (compact JSON) and is admin-only, even under global mode: an ordinary caller never sees SQL shapes.- observability:
PerfTiminggains opt-in per-event detail capture (enableDetail/recordDetail/details) plus the ambientrecordServerTimingDetail. The disclosure gate gains aprivilegedlevel (set byallowPerfDisclosure, read viaisPerfDisclosurePrivileged) so the richer detail can be gated independently of the basic header. - driver-sql: when detail capture is on, the query listener additionally
records each query's parametrized statement (knex's
q.sql,?placeholders) — never the bindings, so no literal row value ever enters the collector. Zero overhead when detail is off. - plugin-hono-server:
X-OS-Debug-Timing: jsonenables detail capture; the middleware emitsX-OS-Debug-Timing-Detail(slowest queries, capped and sanitized to header-safe ASCII) only when the principal is a proven admin.
Basic and global behavior are unchanged;
jsonis purely additive. - observability:
-
2049b6a: feat(observability): admin-gated per-request
Server-TimingviaX-OS-Debug-Timing(#2408)Perf-tuning mode was previously global-only (
serverTimingoption /OS_SERVER_TIMING), which discloses internal phase durations — a mild backend-fingerprinting surface — to every caller. This adds the per-request gating path from the design so an operator can pull a single request'sServer-Timingbreakdown on a live environment without turning the header on for everyone.- observability: a request-scoped disclosure gate (
runWithPerfDisclosure,allowPerfDisclosure,isPerfDisclosureAllowed,PerfDisclosureGate) kept separate from the purePerfTimingcollector and pinned to its ownSymbol.forstore so the middleware and dispatcher share it across module copies. - plugin-hono-server: the Server-Timing middleware is registered by default
(unless
serverTiming: false). It runs the collector when timing is global or the request sendsX-OS-Debug-Timing: 1, and emits the header only when the gate is open.OS_PERF_TIMING=1now also enables global mode. - runtime: after resolving the execution context, the dispatcher opens the gate for admin/service/system principals, so ordinary callers never receive the header even if they send the debug header.
Existing global-mode behavior is unchanged.
- observability: a request-scoped disclosure gate (
-
ce468c8: feat(observability): decompose
Server-Timinginto auth / db / hooks / serialize spans (perf-tuning mode)The opt-in
Server-Timingheader now breaks a request's server time into the phases that actually explain it, so an operator can open DevTools → Network → Timing and see where the time went without standing up an external tracing backend:db— total SQL time with a query count. The SQL driver wires knex'squery/query-responseevents (keyed by__knexQueryUid) and folds each query into one aggregate member (db;dur=210;desc="6 queries") — the query count is the number most useful for spotting N sequential round-trips. Timing is attributed to the originating request viaAsyncLocalStorage, so it is correct under concurrency and never cross-attributes. SQL text is never emitted, only durations and a count.auth— identity / session resolution in the dispatcher, the prime suspect for unexplained data-API overhead.hooks— total business-hook execution time with a hook count, fed through the engine's existingHookMetricsRecorderseam (wired from the runtime, so@objectstack/objectql's leancoretier stays observability-free).serialize— response JSON encoding in the HTTP adapter.
Adds
countServerTiming(name, dur, unit)(andPerfTiming.count) to fold high-frequency phases into a single aggregate member instead of flooding the header. Every phase is a no-op when perf-tuning is off (serverTiming: true/OS_SERVER_TIMING=true), so there is zero measurable overhead on the normal path.Closes #2408.
-
Updated dependencies [f972574]
-
Updated dependencies [6289ec3]
-
Updated dependencies [22013aa]
-
Updated dependencies [3ad3dd5]
-
Updated dependencies [8efa395]
-
Updated dependencies [3a18b60]
-
Updated dependencies [a8aa34c]
-
Updated dependencies [e057f42]
-
Updated dependencies [a3823b2]
-
Updated dependencies [43a3efb]
-
Updated dependencies [524696a]
-
Updated dependencies [bfa3c3f]
-
Updated dependencies [5e3301d]
-
Updated dependencies [dd9f223]
-
Updated dependencies [46e876c]
-
Updated dependencies [5f05de2]
-
Updated dependencies [021ba4c]
-
Updated dependencies [158aa14]
-
Updated dependencies [62a2117]
-
Updated dependencies [83e8f7d]
-
Updated dependencies [d2723e2]
-
Updated dependencies [fefcd54]
-
Updated dependencies [efbcfe1]
-
Updated dependencies [2049b6a]
-
Updated dependencies [beaf2de]
-
Updated dependencies [369eb6e]
-
Updated dependencies [06ff734]
-
Updated dependencies [b659111]
-
Updated dependencies [5754a23]
-
Updated dependencies [6c270a6]
-
Updated dependencies [290e2f0]
-
Updated dependencies [668dd17]
-
Updated dependencies [8abf133]
-
Updated dependencies [e0859b1]
-
Updated dependencies [92f5f19]
-
Updated dependencies [32899e6]
-
Updated dependencies [ce468c8]
-
Updated dependencies [04ecd4e]
-
Updated dependencies [4d5a892]
-
Updated dependencies [16cebeb]
-
Updated dependencies [86d30af]
-
Updated dependencies [8923843]
-
Updated dependencies [a2795f6]
-
Updated dependencies [f16b492]
-
Updated dependencies [4b6fde8]
-
Updated dependencies [2018df9]
-
Updated dependencies [fc5a3a2]
-
Updated dependencies [8ff9210]
- @objectstack/spec@16.0.0
- @objectstack/core@16.0.0
- @objectstack/types@16.0.0
- @objectstack/observability@16.0.0
-
bfa3c3f: Broadcast a
transactionalBatchcapability bit in discovery so clients negotiate the atomic cross-object batch declaratively, instead of runtime-probing 404/405/501 (#3298).The atomic cross-object batch endpoint (
POST {basePath}/batch, #1604 / ADR-0034 item 4) and its typed SDK surface (client.data.batchTransaction, #3271) already shipped, but discovery never told a client whether a backend actually supports it. Consumers (notably ObjectUI'sObjectStackAdapter) had to probe: fire a/batch, read404/405(no route) or501(no runtime transaction), and only then fall back to non-atomic client-side simulation. That is "find out by calling", not capability negotiation — it cannot be decided at connect time and cannot serve as the "minimum backend supports/batch" gate that blocks hard-deleting the non-atomic fallback downstream.WellKnownCapabilitiesSchemagains a requiredtransactionalBatch: boolean, and every discovery producer fills it honestly (declared === enforced), so it never becomes a declared-but-unpopulated bit:@objectstack/metadata-protocol(getDiscovery) — reports whether the runtime engine can honour a transaction (typeof engine.transaction === 'function'). The/batchhandler runs its ops insideengine.transaction(), which degrades to a non-atomic passthrough (or 501) without one.@objectstack/rest(/discovery) — ANDs the engine signal with whether it actually mounts the route (api.enableBatch), so a server with batch disabled reportsfalseeven on a transaction-capable engine (never advertise an endpoint that would 404).@objectstack/plugin-hono-server(standalone discovery) — reportsfalse: this minimal surface registers CRUD only and does not mount/batch(that ships with@objectstack/rest). Under-reporting is the safe direction — a client keeps its correct-but-slower fallback rather than losing atomicity.@objectstack/client— already normalizes hierarchicalcapabilitiesto flat booleans, soclient.capabilities.transactionalBatchis exposed (and now typed) for declarative consumers.
The bit follows the existing capability semantics:
true⟺ the/batchroute is mounted and the runtime can honour a transaction — the exact condition under which the endpoint returns200rather than404/405/501. Additive and behavior-preserving; only the discovery payload gains a field. -
62a2117: Split the overloaded
managedBy: 'system'bucket with an explicitengine-ownedvalue (ADR-0103 addendum, #3343). ADR-0103 deferred the enum split ("revisitable later as a rename") because a newmanagedByvalue would fall through to the fully-editableplatformdefault on deployed Console clients. Both reasons against it are now retired — the server-side write guard /apiMethodsreconciliation //me/permissionsclamp make that fallthrough cosmetic (the write is rejected regardless of what the client renders), and objectui#2712 closed the UI union — so v16 lands it, additively.- New enum value
engine-ownedwith the same all-locked default affordance row assystem(create/import/edit/delete: false,exportCsv: true). It joinsENGINE_OWNED_BUCKETS(the engine write guard) andGUARDED_WRITE_BUCKETS(the/me/permissionsclamp); the guard,reconcileManagedApiMethods, and the clamp mechanisms are unchanged —engine-ownedis an explicit member of the set they already covered by resolved affordance. - 20 objects relabelled
system → engine-owned— the ones the engine owns end to end and that declared no write-openinguserActions(the metadata store, jobs, approval runtime rows, sharing rows,sys_automation_run, the messaging delivery/receipt pipeline,sys_secret, settings). One-line, behaviour-identical per object. - 8 admin/user-writable objects keep
managedBy: 'system'(the RBAC link tables,sys_user_preference,sys_approval_delegation, the messaging config grids) —systemnow reads as "engine-managed schema, writable viauserActions".
Behaviour-, enforcement- and wire-identical: resolved affordances, the guard verdict, the 405
apiMethodsreconciliation, and the permissions clamp are the same before and after — this is a self-documenting relabel, not a policy change. No data migration (managedByis schema metadata) and no code branches on the'system'literal. Retiring the overloadedsystementirely (moving the 8 writable objects to a dedicated bucket) is a breaking rename deferred to v17. - New enum value
- Updated dependencies [6289ec3]
- Updated dependencies [8efa395]
- Updated dependencies [bfa3c3f]
- Updated dependencies [62a2117]
- Updated dependencies [06ff734]
- @objectstack/spec@16.0.0-rc.1
- @objectstack/core@16.0.0-rc.1
- @objectstack/observability@16.0.0-rc.1
- @objectstack/types@16.0.0-rc.1
-
22013aa: Split the overloaded
managedBy: 'system'bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220). Thesystembucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row asbetter-auth/append-onlybut, unlikebetter-auth, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap).Rather than add a new
managedByenum value (which would fall through to fully-editableplatformdefaults on already-deployed Console clients), the write policy is now the resolved affordance (resolveCrudAffordances= bucket default +userActions), and engine-owned is defined as asystem/append-onlyobject that grants no write:- Writable set declares
userActions— the RBAC link tables (sys_user_position,sys_user_permission_set,sys_position_permission_set),sys_user_preference,sys_approval_delegation, and the messaging config grids (sys_notification_preference/…_subscription/…_template) now declareuserActions: { create, edit, delete: true }. The affordance is a declaration only — theDelegatedAdminGate/ RLS / permission sets remain the authz. - Engine-owned objects locked to reads —
apiMethods: ['get','list']added where absent (jobs, notifications, approval request/approver/token/action,sys_record_share,sys_automation_run, mail/settings/secret audit, the messaging delivery pipeline).sys_secretis explicitly read-locked (an emptyapiMethodsarray fails open). sys_import_jobstays engine-owned: the REST import route now writes its job rowsisSystem-elevated (attribution preserved via the explicitcreated_bystamp) and the object is locked to['get','list'].- New engine write guard (
assertEngineOwnedWriteAllowed, plugin-security) fail-closed rejects user-context generic writes to engine-ownedsystem/append-onlyobjects, keyed off the resolved affordance;isSystemand context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. reconcileManagedApiMethods(objectql registry) now runs for every managed bucket, not justbetter-auth: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049)./me/permissionsclamp (plugin-hono-server) now clampssystem/append-onlyas well asbetter-auth, so the client hint reflectspermission ∩ guard.
Potentially breaking: a downstream/third-party
systemobject that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. DeclareuserActionsopening the verbs the object legitimately takes from a user context.better-authkeeps plugin-auth's identity write guard unchanged; the row-levelmanaged_byprovenance vocabulary (ADR-0066) is a different axis and is untouched. - Writable set declares
-
efbcfe1: feat(observability): admin-only richer per-request timing detail via
X-OS-Debug-Timing: json(#2408)Completes the optional "richer JSON" diagnostic from #2408. In addition to the basic
Server-Timingheader, an admin/service caller can now request a per-query breakdown — the slowest SQL statements and a query count — by sendingX-OS-Debug-Timing: json. The detail is returned in a separateX-OS-Debug-Timing-Detailresponse header (compact JSON) and is admin-only, even under global mode: an ordinary caller never sees SQL shapes.- observability:
PerfTiminggains opt-in per-event detail capture (enableDetail/recordDetail/details) plus the ambientrecordServerTimingDetail. The disclosure gate gains aprivilegedlevel (set byallowPerfDisclosure, read viaisPerfDisclosurePrivileged) so the richer detail can be gated independently of the basic header. - driver-sql: when detail capture is on, the query listener additionally
records each query's parametrized statement (knex's
q.sql,?placeholders) — never the bindings, so no literal row value ever enters the collector. Zero overhead when detail is off. - plugin-hono-server:
X-OS-Debug-Timing: jsonenables detail capture; the middleware emitsX-OS-Debug-Timing-Detail(slowest queries, capped and sanitized to header-safe ASCII) only when the principal is a proven admin.
Basic and global behavior are unchanged;
jsonis purely additive. - observability:
-
2049b6a: feat(observability): admin-gated per-request
Server-TimingviaX-OS-Debug-Timing(#2408)Perf-tuning mode was previously global-only (
serverTimingoption /OS_SERVER_TIMING), which discloses internal phase durations — a mild backend-fingerprinting surface — to every caller. This adds the per-request gating path from the design so an operator can pull a single request'sServer-Timingbreakdown on a live environment without turning the header on for everyone.- observability: a request-scoped disclosure gate (
runWithPerfDisclosure,allowPerfDisclosure,isPerfDisclosureAllowed,PerfDisclosureGate) kept separate from the purePerfTimingcollector and pinned to its ownSymbol.forstore so the middleware and dispatcher share it across module copies. - plugin-hono-server: the Server-Timing middleware is registered by default
(unless
serverTiming: false). It runs the collector when timing is global or the request sendsX-OS-Debug-Timing: 1, and emits the header only when the gate is open.OS_PERF_TIMING=1now also enables global mode. - runtime: after resolving the execution context, the dispatcher opens the gate for admin/service/system principals, so ordinary callers never receive the header even if they send the debug header.
Existing global-mode behavior is unchanged.
- observability: a request-scoped disclosure gate (
-
ce468c8: feat(observability): decompose
Server-Timinginto auth / db / hooks / serialize spans (perf-tuning mode)The opt-in
Server-Timingheader now breaks a request's server time into the phases that actually explain it, so an operator can open DevTools → Network → Timing and see where the time went without standing up an external tracing backend:db— total SQL time with a query count. The SQL driver wires knex'squery/query-responseevents (keyed by__knexQueryUid) and folds each query into one aggregate member (db;dur=210;desc="6 queries") — the query count is the number most useful for spotting N sequential round-trips. Timing is attributed to the originating request viaAsyncLocalStorage, so it is correct under concurrency and never cross-attributes. SQL text is never emitted, only durations and a count.auth— identity / session resolution in the dispatcher, the prime suspect for unexplained data-API overhead.hooks— total business-hook execution time with a hook count, fed through the engine's existingHookMetricsRecorderseam (wired from the runtime, so@objectstack/objectql's leancoretier stays observability-free).serialize— response JSON encoding in the HTTP adapter.
Adds
countServerTiming(name, dur, unit)(andPerfTiming.count) to fold high-frequency phases into a single aggregate member instead of flooding the header. Every phase is a no-op when perf-tuning is off (serverTiming: true/OS_SERVER_TIMING=true), so there is zero measurable overhead on the normal path.Closes #2408.
-
Updated dependencies [f972574]
-
Updated dependencies [22013aa]
-
Updated dependencies [3ad3dd5]
-
Updated dependencies [3a18b60]
-
Updated dependencies [a8aa34c]
-
Updated dependencies [e057f42]
-
Updated dependencies [a3823b2]
-
Updated dependencies [43a3efb]
-
Updated dependencies [524696a]
-
Updated dependencies [5e3301d]
-
Updated dependencies [dd9f223]
-
Updated dependencies [46e876c]
-
Updated dependencies [5f05de2]
-
Updated dependencies [021ba4c]
-
Updated dependencies [158aa14]
-
Updated dependencies [83e8f7d]
-
Updated dependencies [d2723e2]
-
Updated dependencies [fefcd54]
-
Updated dependencies [efbcfe1]
-
Updated dependencies [2049b6a]
-
Updated dependencies [beaf2de]
-
Updated dependencies [369eb6e]
-
Updated dependencies [b659111]
-
Updated dependencies [5754a23]
-
Updated dependencies [6c270a6]
-
Updated dependencies [290e2f0]
-
Updated dependencies [668dd17]
-
Updated dependencies [8abf133]
-
Updated dependencies [e0859b1]
-
Updated dependencies [92f5f19]
-
Updated dependencies [32899e6]
-
Updated dependencies [ce468c8]
-
Updated dependencies [04ecd4e]
-
Updated dependencies [4d5a892]
-
Updated dependencies [16cebeb]
-
Updated dependencies [86d30af]
-
Updated dependencies [8923843]
-
Updated dependencies [a2795f6]
-
Updated dependencies [f16b492]
-
Updated dependencies [4b6fde8]
-
Updated dependencies [2018df9]
-
Updated dependencies [fc5a3a2]
- @objectstack/spec@16.0.0-rc.0
- @objectstack/core@16.0.0-rc.0
- @objectstack/types@16.0.0-rc.0
- @objectstack/observability@16.0.0-rc.0
- @objectstack/spec@15.1.1
- @objectstack/core@15.1.1
- @objectstack/types@15.1.1
- @objectstack/observability@15.1.1
-
f531a26: fix(security): enforce the anonymous-deny posture uniformly across HTTP surfaces (#2567)
The ADR-0056 D2
requireAuthflip made REST/data/*deny-anonymous by default, but three sibling surfaces reached ObjectQL without passing through the gate — so the platform's anonymous posture was inconsistent by surface: an anonymous caller denied on/datacould read the same object data through a different door. This closes the remaining two gaps (the/metagate had already landed) and pins every surface with a conformance row.-
Dispatcher GraphQL (
runtime/http-dispatcher.ts,dispatcher-plugin.ts):POST /graphqlreachedkernel.graphql, whose security middleware falls open for an anonymous context.handleGraphQLnow applies the samerequireAuthgate as/dataand/meta, resolving identity for the direct route that does not flow throughdispatch(). The dispatcher'srequireAuthdefault is aligned with the REST plugin's (?? true) so a bare host no longer denies anonymous/datawhile serving the same rows over/graphql; an explicitrequireAuth: falseopt-out is honoured and logs a boot warning. -
Raw-hono standard
/dataroutes (plugin-hono-server/hono-plugin.ts): these delegate straight to ObjectQL and were only shadowed when the REST plugin registered the same paths first — so secure-by-default depended on plugin registration order. Each route now consultsrequireAuth(secure by default, mirroringrest-server.ts), making the deny decision a property of this entry point too. Order no longer affects the anonymous posture.
Behaviour change: on a
requireAuthdeployment (the secure default), anonymousPOST /graphqland anonymous raw-hono/datanow return 401. Deployments that intentionally serve these surfaces publicly setrequireAuth: false(a boot warning is logged). Proven end-to-end on the platform default inshowcase-anonymous-deny-surfaces.dogfood.test.ts, with handler-level regression coverage inhttp-dispatcher.requireauth.test.tsandhono-anonymous-deny.test.ts, and pinned by three new authz-conformance rows. -
-
f531a26: feat(discovery): honest capabilities — standardized stub/fallback marker + realtime route honesty (ADR-0076 D12/A1.5 framework slice, #2462)
Spec — new service self-description marker for honest discovery (ADR-0076 D12):
SERVICE_SELF_INFO_KEY(__serviceInfo),ServiceSelfInfoSchema/ServiceSelfInfo, andreadServiceSelfInfo(), which also normalizes plugin-dev's legacy_dev: trueflag to{ status: 'stub', handlerReady: false }. A registered service that is a stub / dev fake / degraded fallback self-identifies via this marker; a fully real service carries no marker.Runtime + metadata-protocol — both discovery builders (
HttpDispatcher.getDiscoveryInfoand the protocol shim'sgetDiscovery) now honor the marker instead of hardcodingstatus: 'available', handlerReady: truefor every registered service. Dev stubs reportstub, the ObjectQL analytics fallback reportsdegraded(it keeps serving — no/analytics404), and consumers can finally truststatus === 'available'/handlerReady === true.Realtime honesty fix — discovery no longer advertises a
/realtimeroute orwebsockets: true:service-realtimeis an in-process pub/sub bus, no dispatcher branch or plugin mounts any/realtimeHTTP surface, so the advertised route always 404'd. The registered service now reportsstatus: 'degraded', handlerReady: falsewith no route (clients using the SDK are unaffected — it falls back to the conventional path, which behaves exactly as before). Also corrects the advertised realtime provider from the nonexistentplugin-realtimetoservice-realtime.REST (A1.5) — the REST layer's protocol dependency is narrowed from the
ObjectStackProtocolgod-union to the newRestProtocol = DataProtocol & MetadataProtocolslice (exported from@objectstack/rest), per the ADR-0076 D9 incremental narrowing guidance. Type-level only; no runtime change. -
f531a26: refactor(security): converge the anonymous-deny decision into one shared function + a source-enumerating ratchet (#2567 Phase 2)
Phase 1 gated every HTTP surface (REST
/data, dispatcher/graphql+/meta, raw-hono/data) against the secure-by-defaultrequireAuthposture, but each seam hand-rolled the same!userId && !isSystem → 401check. Phase 2 removes that duplication and pins the surfaces so a new ungated entry point fails CI.- New
shouldDenyAnonymousin@objectstack/core(security/anonymous-deny.ts) — the single anonymous-deny decision + shared 401 body/constants, mirroring theauth-gate.tspattern (pure function so the seams can never drift). All five seams — RESTenforceAuth, dispatcherhandleGraphQL/handleMetadata/handleAI, honodenyAnonymous— now delegate to it. Pure refactor: no runtime behavior change (verified by the unchanged Phase-1 handler + e2e proofs). Identity resolution and the dynamic exemptions (public-form grants, share-link tokens) are untouched — they run upstream and only ever hand the seam an already-resolved context. - A
discover()ratchet on the authz-conformance matrix — it statically enumerates the data/meta/graphql HTTP entry points from source (curated per-file probes, control-plane routes excluded) and asserts each is classified by a matrixcoverskey. A new/data//meta//graphqlroute (or a removed/stalecovers) now fails CI as UNCLASSIFIED / STALE, not in review. A companion negative test proves the ratchet bites.
A design trap is guarded:
isAuthGateAllowlisted(undefined)returnstrue, so a body-routed seam (GraphQL, which has no request path) must pass no path — the shared function's non-empty-path guard denies anonymous unconditionally there, never falling through to the control-plane allowlist. - New
-
f531a26: CORS default
allowHeadersnow includesIf-Match. The REST record update accepts the OCC token as anIf-Matchheader (objectui's record-level inline edit sends it on every save), but the preflight allow-list omitted it — so on any split-origin deployment (console dev server against a backend on another origin) the browser failed the preflight and every inline-edit save died with "Failed to fetch". Found live while dogfooding objectui#2572; same split-origin failure class as the #2548 Bearer fixes. Explicit user-suppliedallowHeadersstill win unchanged. -
627f225: feat(spec): userActions.edit/delete accept per-record CEL predicates (objectui#2614)
userActions.edit/userActions.deletenow accept, in addition to the plain boolean, an object form{ enabled?, visibleWhen?, disabledWhen? }(RowCrudActionOverrideSchema) so the built-in row Edit/Delete affordances can be hidden or disabled per record via CEL predicates — the same evaluation contract custom row actions already use.visibleWhenfalse → button not rendered (fail-closed);disabledWhentrue → rendered disabled (fail-soft). Advisory UI gating only; server enforcement stays with permissions/hooks.resolveCrudAffordances()keeps returning the resolved booleans (enabledfalls back to themanagedBybucket default) and now surfaces the predicates aseditPredicates/deletePredicates. Boolean-only inputs produce byte-identical output — zero behavior change for existing schemas.clampManagedObjectWrites(ADR-0092 D2 hint clamp) treats the object form by its explicitenabledflag only: per-record predicates are not a write grant, so managed objects stay fail-closed unlessenabled === true. -
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [3fe9df1]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [4109153]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [627f225]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
-
Updated dependencies [f531a26]
- @objectstack/spec@15.1.0
- @objectstack/core@15.1.0
- @objectstack/types@15.1.0
- @objectstack/observability@15.1.0
- Updated dependencies [28b7c28]
- Updated dependencies [13749ec]
- Updated dependencies [e62c233]
- Updated dependencies [ed61c9b]
- Updated dependencies [31d04d4]
- @objectstack/spec@15.0.0
- @objectstack/core@15.0.0
- @objectstack/observability@15.0.0
- @objectstack/types@15.0.0
- Updated dependencies [16b4bf6]
- Updated dependencies [16b4bf6]
- Updated dependencies [10e8983]
- Updated dependencies [607aaf4]
- Updated dependencies [bb71321]
- @objectstack/spec@14.8.0
- @objectstack/core@14.8.0
- @objectstack/observability@14.8.0
- @objectstack/types@14.8.0
- Updated dependencies [d6a72eb]
- Updated dependencies [824a395]
- @objectstack/spec@14.7.0
- @objectstack/types@14.7.0
- @objectstack/core@14.7.0
- @objectstack/observability@14.7.0
- Updated dependencies [609cb13]
- Updated dependencies [ce6d151]
- @objectstack/spec@14.6.0
- @objectstack/core@14.6.0
- @objectstack/observability@14.6.0
- @objectstack/types@14.6.0
-
6da03ee: fix(security):
/me/permissionsnow reflects permission-set ∩ identity-write-guard, matching real server enforcement (ADR-0057 D10)The
/api/v1/auth/me/permissionsper-object map merged each permission set's explicitobjectsentries most-permissively per key, but treated'*'and named objects as independent keys — so a wildcard "Modify/View All Data" grant was never propagated into a per-object entry another set explicitly denied. That made the client's field-level security STRICTER than the server's actual enforcement (PermissionEvaluator.checkObjectPermissionallows as soon as any set grants, including via the'*'modifyAll/viewAll super-user bypass, with no deny-wins).The real effective answer for a user-context caller is
permission-set grant ∩ identity-write-guard policy, and the payload now computes both:foldWildcardSuperUserlifts each per-object entry's read/write bits when the merged'*'is a super-user grant — fixing the false-NEGATIVE where a platform admin (admin_full_access'*': {modifyAllRecords}) who also holdsorganization_admin(explicit identity denies) resolved tosys_user.allowEdit:falseand a disabled edit form, though the server accepts the write (PATCH /data/sys_user {name}→ 200).clampManagedObjectWritesre-clampsmanagedBy: 'better-auth'objects by their write affordance — fixing the false-POSITIVE the fold would otherwise introduce: the identity write guard (ADR-0092 D2) blocks user-context writes on identity tables except where the object opted in (userActions.edit), sosys_member/sys_account/sys_sessionstayallowEdit:falsefor the admin (read stays granted). Onlybetter-authobjects are clamped — the guard covers only them;system/config/append-onlyobjects have no such guard and their permission-set result stands.
Net: the Console's per-object FLS now equals real server enforcement — the ADR-0092 D4
sys_userprofile-edit affordance is unblocked for platform admins (the guard still narrows the write to{name, image}), and no other identity table is shown as editable when the guard would reject it. -
Updated dependencies [526805e]
-
Updated dependencies [d79ca07]
-
Updated dependencies [33ebd34]
-
Updated dependencies [c044f08]
-
Updated dependencies [01274eb]
- @objectstack/spec@14.5.0
- @objectstack/core@14.5.0
- @objectstack/observability@14.5.0
- @objectstack/types@14.5.0
- Updated dependencies [7953832]
- Updated dependencies [82e745e]
- Updated dependencies [f3035bd]
- Updated dependencies [82c0d94]
- Updated dependencies [7449476]
- @objectstack/spec@14.4.0
- @objectstack/core@14.4.0
- @objectstack/observability@14.4.0
- @objectstack/types@14.4.0
- Updated dependencies [2a71f48]
- Updated dependencies [02f6af4]
- Updated dependencies [c1064f1]
- @objectstack/spec@14.3.0
- @objectstack/core@14.3.0
- @objectstack/observability@14.3.0
- @objectstack/types@14.3.0
-
ac8f029: Two ADR-0090 D5 closures (#2752, #2753):
GET /me/appssources the engine registry. Stack apps are registered into the engine registry (runtime AppPlugin), not the metadata service —metadata.list('app')returned[]for every principal, leavingtabPermissionsandAppSchema.requiredPermissionswith no enforced consumer. The endpoint now readsregistry.getAllApps()(same authority as the meta routes, nav contributions merged) with the metadata service as an additive fallback; the capability and tab filters are unchanged and now actually run.The default baseline binds to the
everyoneanchor.member_defaultcarriedallowDeleteon its'*'grant — an anchor-forbidden bit — so bootstrap refused theeveryonebinding on every boot and the baseline flowed only through the separate fallback channel D5 explicitly rejected. Two aligned changes:describeHighPrivilegeBits(spec) is calibrated to the exact ADR-0090 D5 bit list (VAMA, delete/purge/transfer, systemPermissions). A plain'*'wildcard is no longer high-privilege by itself; the wildcard ban moves to the GUEST tier where D9 specifies it (describeAnchorForbiddenBits).member_defaultdropsallowDeletefrom the wildcard. Behavior change: deleting records is no longer a baseline right — members keep create/read/edit-own; domains that want member deletes grant them per object via an ordinary position-distributed set. The owner-scoped delete RLS stays as a narrowing defense for members who receive a delete bit elsewhere.
With the baseline anchor-safe, bootstrap's existing binding path succeeds: "what new users get" is now literally "what is bound to
everyone" — same table, same audit, same explain path (proven by the newme-apps-and-everyone-baselinedogfood). -
Updated dependencies [ac8f029]
-
Updated dependencies [4ab9958]
- @objectstack/spec@14.2.0
- @objectstack/core@14.2.0
- @objectstack/observability@14.2.0
- @objectstack/types@14.2.0
- Updated dependencies [5a8465f]
- Updated dependencies [7f8620b]
- Updated dependencies [82ba3a6]
- @objectstack/spec@14.1.0
- @objectstack/core@14.1.0
- @objectstack/observability@14.1.0
- @objectstack/types@14.1.0
- Updated dependencies [0a8e685]
- Updated dependencies [afa8115]
- Updated dependencies [80f12ca]
- Updated dependencies [e2fa074]
- Updated dependencies [23c8668]
- Updated dependencies [29f017d]
- Updated dependencies [216fa9a]
- Updated dependencies [6c22b12]
- @objectstack/spec@14.0.0
- @objectstack/core@14.0.0
- @objectstack/observability@14.0.0
- @objectstack/types@14.0.0
-
b1081b8: Return
405 Method Not Allowed(with an accurateAllowheader and a descriptive body) instead of an opaque{"error":"Not found"}404 when a request hits a registered path under the wrong HTTP method.Hono routes a method mismatch to the same
notFoundsink as a genuinely missing path, so aPOSTto aPUT-only route (e.g. the metadata save endpointPUT /api/v1/meta/:type/:name) gave callers no hint that the path exists under another verb (#2684). The server now tracks every registered(method, pattern)pair and re-matches the request path in thenotFoundhandler: matching another method yields a 405; matching nothing stays a 404. This is framework-wide — every registered endpoint benefits. Static/SPA catch-alls registered straight on the raw Hono app are not tracked and never produce a spurious 405. -
Updated dependencies [6d83431]
-
Updated dependencies [01917c2]
-
Updated dependencies [b271691]
-
Updated dependencies [a5a1e41]
-
Updated dependencies [466adf6]
-
Updated dependencies [57b89b4]
-
Updated dependencies [5be00c3]
-
Updated dependencies [466adf6]
-
Updated dependencies [2bee609]
-
Updated dependencies [fc7e7f7]
- @objectstack/spec@13.0.0
- @objectstack/core@13.0.0
- @objectstack/types@13.0.0
- @objectstack/observability@13.0.0
- Updated dependencies [6cebf22]
- Updated dependencies [21420d9]
- @objectstack/spec@12.6.0
- @objectstack/core@12.6.0
- @objectstack/observability@12.6.0
- @objectstack/types@12.6.0
- Updated dependencies [8b3d363]
- @objectstack/spec@12.5.0
- @objectstack/core@12.5.0
- @objectstack/observability@12.5.0
- @objectstack/types@12.5.0
- Updated dependencies [60dc3ba]
- @objectstack/spec@12.4.0
- @objectstack/core@12.4.0
- @objectstack/observability@12.4.0
- @objectstack/types@12.4.0
- Updated dependencies [e7eceec]
- @objectstack/spec@12.3.0
- @objectstack/core@12.3.0
- @objectstack/observability@12.3.0
- @objectstack/types@12.3.0
- Updated dependencies [fce8ff4]
- Updated dependencies [3962023]
- Updated dependencies [2bb193d]
- Updated dependencies [0426d27]
- Updated dependencies [da807f7]
- Updated dependencies [4f5b791]
- @objectstack/spec@12.2.0
- @objectstack/core@12.2.0
- @objectstack/observability@12.2.0
- @objectstack/types@12.2.0
- Updated dependencies [93e6d02]
- @objectstack/spec@12.1.0
- @objectstack/core@12.1.0
- @objectstack/observability@12.1.0
- @objectstack/types@12.1.0
- Updated dependencies [a8df396]
- Updated dependencies [e695fe0]
- Updated dependencies [7c09621]
- Updated dependencies [7709db4]
- Updated dependencies [2082109]
- Updated dependencies [7c09621]
- Updated dependencies [9860de4]
- Updated dependencies [069c205]
- @objectstack/spec@12.0.0
- @objectstack/core@12.0.0
- @objectstack/observability@12.0.0
- @objectstack/types@12.0.0
- Updated dependencies [6a9397e]
- Updated dependencies [c0efe5d]
- @objectstack/spec@11.10.0
- @objectstack/core@11.10.0
- @objectstack/observability@11.10.0
- @objectstack/types@11.10.0
- Updated dependencies [d3595d9]
- @objectstack/spec@11.9.0
- @objectstack/core@11.9.0
- @objectstack/observability@11.9.0
- @objectstack/types@11.9.0
- @objectstack/spec@11.8.0
- @objectstack/core@11.8.0
- @objectstack/types@11.8.0
- @objectstack/observability@11.8.0
- Updated dependencies [5178906]
- @objectstack/spec@11.7.0
- @objectstack/core@11.7.0
- @objectstack/observability@11.7.0
- @objectstack/types@11.7.0
- @objectstack/spec@11.6.0
- @objectstack/core@11.6.0
- @objectstack/types@11.6.0
- @objectstack/observability@11.6.0
- Updated dependencies [6ee4f04]
- Updated dependencies [c1e3a65]
- @objectstack/spec@11.5.0
- @objectstack/core@11.5.0
- @objectstack/observability@11.5.0
- @objectstack/types@11.5.0
- Updated dependencies [5821c51]
- Updated dependencies [a0fce3f]
- @objectstack/spec@11.4.0
- @objectstack/core@11.4.0
- @objectstack/observability@11.4.0
- @objectstack/types@11.4.0
- Updated dependencies [58e8e31]
- Updated dependencies [b4a5df0]
- @objectstack/spec@11.3.0
- @objectstack/core@11.3.0
- @objectstack/observability@11.3.0
- @objectstack/types@11.3.0
- Updated dependencies [d0f4b13]
- Updated dependencies [302bdab]
- @objectstack/spec@11.2.0
- @objectstack/core@11.2.0
- @objectstack/observability@11.2.0
- @objectstack/types@11.2.0
-
dc2990f: Observability: per-request performance timing surfaced via the
Server-Timingresponse header ("perf-tuning mode").@objectstack/observabilitygains a tiny, dependency-freePerfTimingcollector plus anAsyncLocalStorage-backed ambient API (runWithPerfTiming/currentPerfTimingand the no-op-when-disabled free functionsmeasureServerTiming/startServerTiming/recordServerTiming) and a spec-compliantformatServerTimingserializer that sanitizes names to tokens and quotes/escapes descriptions (no header injection).The Hono server plugin can now emit
Server-Timingper request. It is off by default — the header discloses internal phase durations, which is a backend-fingerprinting surface — and opt-in vianew HonoServerPlugin({ serverTiming: true })orOS_SERVER_TIMING=true(so it works through the defaultos serve). When enabled, every response carriestotal(measured by an outer middleware that brackets the whole request) plus the adapter-contributedparseandhandlersub-phases; any code on the request's async call chain can add its own phases via the ambient API. When disabled, the timing call sites are zero-overhead no-ops.
- Updated dependencies [ce0b4f6]
- Updated dependencies [9ccfcd6]
- Updated dependencies [dc2990f]
- Updated dependencies [ecf193f]
- Updated dependencies [51bec81]
- Updated dependencies [3e593a7]
- Updated dependencies [fdb41c0]
- Updated dependencies [63d5403]
- @objectstack/core@11.1.0
- @objectstack/observability@11.1.0
- @objectstack/spec@11.1.0
- @objectstack/types@11.1.0
- Updated dependencies [ab5718a]
- Updated dependencies [4845c12]
- Updated dependencies [c1a754a]
- Updated dependencies [6fbe91f]
- Updated dependencies [715d667]
- Updated dependencies [5eef4cf]
- Updated dependencies [72759e1]
- Updated dependencies [6c4fbd9]
- Updated dependencies [ef3ed67]
- Updated dependencies [cd51229]
- Updated dependencies [7697a0e]
- Updated dependencies [e7e04f1]
- Updated dependencies [cfd5ac4]
- Updated dependencies [2be5c1f]
- Updated dependencies [ad143ce]
- Updated dependencies [5c4a8c8]
- Updated dependencies [3afaeed]
- Updated dependencies [795b6d1]
- Updated dependencies [8801c02]
- Updated dependencies [3d04e06]
- Updated dependencies [4a84c98]
- Updated dependencies [c715d25]
- Updated dependencies [aa33b02]
- Updated dependencies [d980f0d]
- Updated dependencies [a658523]
- Updated dependencies [82ff91c]
- Updated dependencies [638f472]
- @objectstack/spec@11.0.0
- @objectstack/types@11.0.0
- @objectstack/core@11.0.0
- @objectstack/spec@10.3.0
- @objectstack/core@10.3.0
- @objectstack/types@10.3.0
- Updated dependencies [b496498]
- @objectstack/spec@10.2.0
- @objectstack/core@10.2.0
- @objectstack/types@10.2.0
- Updated dependencies [49da36e]
- Updated dependencies [ac79f16]
- @objectstack/spec@10.1.0
- @objectstack/core@10.1.0
- @objectstack/types@10.1.0
-
00c32f2: Expose resolved regional defaults to every authenticated user.
Adds
GET /api/v1/auth/me/localizationreturning the request tenant's resolved{ currency, locale, timezone }from the ExecutionContext (ADR-0053). ThelocalizationSETTINGS are gated tosetup.access, but the resolved defaults are needed by every renderer to format currency/dates/numbers — so they are surfaced here without that gate. Enables a client to format a currency field in the tenant's default currency when the field omits its own.
- Updated dependencies [d7ff626]
- Updated dependencies [2a1b16b]
- Updated dependencies [e16f2a8]
- Updated dependencies [e411a82]
- Updated dependencies [a581385]
- Updated dependencies [d5f6d29]
- Updated dependencies [220ce5b]
- Updated dependencies [3efe334]
- Updated dependencies [feead7e]
- Updated dependencies [6ca20b3]
- Updated dependencies [5f875fe]
- Updated dependencies [b469950]
- @objectstack/spec@10.0.0
- @objectstack/core@10.0.0
- @objectstack/types@10.0.0
- Updated dependencies [e7f6539]
- Updated dependencies [2365d07]
- Updated dependencies [6595b53]
- Updated dependencies [fa8964d]
- Updated dependencies [36138c7]
- Updated dependencies [a8e4f3b]
- Updated dependencies [4c213c2]
- Updated dependencies [2afb612]
- @objectstack/spec@9.11.0
- @objectstack/core@9.11.0
- @objectstack/types@9.11.0
- Updated dependencies [db02bd5]
- Updated dependencies [641675d]
- Updated dependencies [94e9040]
- Updated dependencies [1f88fd9]
- Updated dependencies [1f88fd9]
- @objectstack/spec@9.10.0
- @objectstack/core@9.10.0
- @objectstack/types@9.10.0
- @objectstack/spec@9.9.1
- @objectstack/core@9.9.1
- @objectstack/types@9.9.1
- Updated dependencies [84249a4]
- Updated dependencies [11af299]
- Updated dependencies [d5774b5]
- Updated dependencies [134043a]
- Updated dependencies [90108e0]
- Updated dependencies [9afeb2d]
- Updated dependencies [6bec07e]
- Updated dependencies [601cc11]
- Updated dependencies [575448d]
- @objectstack/spec@9.9.0
- @objectstack/core@9.9.0
- @objectstack/types@9.9.0
- Updated dependencies [97c55b3]
- Updated dependencies [1b1f490]
- @objectstack/spec@9.8.0
- @objectstack/core@9.8.0
- @objectstack/types@9.8.0
- @objectstack/spec@9.7.0
- @objectstack/core@9.7.0
- @objectstack/types@9.7.0
- Updated dependencies [d1e930a]
- Updated dependencies [71578f2]
- Updated dependencies [5e3a301]
- Updated dependencies [5db2742]
- @objectstack/spec@9.6.0
- @objectstack/core@9.6.0
- @objectstack/types@9.6.0
- Updated dependencies [ee72aae]
- @objectstack/spec@9.5.1
- @objectstack/core@9.5.1
- @objectstack/types@9.5.1
- Updated dependencies [d08551c]
- Updated dependencies [707aeed]
- Updated dependencies [7a103d4]
- Updated dependencies [4b01250]
- @objectstack/spec@9.5.0
- @objectstack/core@9.5.0
- @objectstack/types@9.5.0
- Updated dependencies [060467a]
- Updated dependencies [0856476]
- Updated dependencies [b678d8c]
- Updated dependencies [b678d8c]
- Updated dependencies [b678d8c]
- @objectstack/spec@9.4.0
- @objectstack/core@9.4.0
- @objectstack/types@9.4.0
- Updated dependencies [1ada658]
- Updated dependencies [3219191]
- Updated dependencies [290f631]
- Updated dependencies [50b7b47]
- Updated dependencies [f15d6f6]
- Updated dependencies [f8684ea]
- Updated dependencies [b4765be]
- @objectstack/spec@9.3.0
- @objectstack/core@9.3.0
- @objectstack/types@9.3.0
- Updated dependencies [2f57b75]
- Updated dependencies [2f57b75]
- @objectstack/spec@9.2.0
- @objectstack/core@9.2.0
- @objectstack/types@9.2.0
- Updated dependencies [b9062c9]
- @objectstack/spec@9.1.0
- @objectstack/core@9.1.0
- @objectstack/types@9.1.0
- Updated dependencies [1817845]
- @objectstack/spec@9.0.1
- @objectstack/core@9.0.1
- @objectstack/types@9.0.1
- Updated dependencies [4c3f693]
- Updated dependencies [0bf39f1]
- Updated dependencies [f533f42]
- Updated dependencies [1c83ee8]
- @objectstack/spec@9.0.0
- @objectstack/core@9.0.0
- @objectstack/types@9.0.0
- @objectstack/spec@8.0.1
- @objectstack/core@8.0.1
- @objectstack/types@8.0.1
-
93f97b2: fix(hono-server): drain in-flight requests on shutdown instead of force-closing (P1-3)
HonoHttpServer.close()calledcloseAllConnections(), which terminated active connections mid-response — so a SIGTERM during a rolling deploy dropped in-flight requests. It now drains gracefully:server.close()stops accepting new connections and lets active requests finish,closeIdleConnections()releases idle keep-alive sockets so the process exits promptly, and a bounded drain window (default 10s, configurable, well under the kernel's 60sshutdownTimeout) force-closes only the stragglers so shutdown can't hang.Note: the kernel already handles SIGINT/SIGTERM/SIGQUIT with an ordered, timeout-bounded shutdown — this fixes the one place that wasn't draining.
-
Updated dependencies [a46c017]
-
Updated dependencies [b990b89]
-
Updated dependencies [99111ec]
-
Updated dependencies [d5a8161]
-
Updated dependencies [5cf1f1b]
-
Updated dependencies [9ef89d4]
-
Updated dependencies [3306d2f]
-
Updated dependencies [c262301]
-
Updated dependencies [bc44195]
-
Updated dependencies [9e2e229]
- @objectstack/spec@8.0.0
- @objectstack/core@8.0.0
- @objectstack/types@8.0.0
- @objectstack/spec@7.9.0
- @objectstack/core@7.9.0
- @objectstack/types@7.9.0
- Updated dependencies [06f2bbb]
- Updated dependencies [36719db]
- Updated dependencies [424ab26]
- @objectstack/spec@7.8.0
- @objectstack/core@7.8.0
- @objectstack/types@7.8.0
- Updated dependencies [b391955]
- Updated dependencies [f06b64e]
- Updated dependencies [023bf93]
- @objectstack/spec@7.7.0
- @objectstack/core@7.7.0
- @objectstack/types@7.7.0
- Updated dependencies [955d4c8]
- Updated dependencies [c4a4cbd]
- Updated dependencies [b046ec2]
- Updated dependencies [2170ad9]
- Updated dependencies [02d6359]
- Updated dependencies [7648242]
- Updated dependencies [8fa1e7f]
- Updated dependencies [55866f5]
- Updated dependencies [60f9c45]
- @objectstack/spec@7.6.0
- @objectstack/core@7.6.0
- @objectstack/types@7.6.0
- @objectstack/spec@7.5.0
- @objectstack/core@7.5.0
- @objectstack/types@7.5.0
- @objectstack/spec@7.4.1
- @objectstack/core@7.4.1
- @objectstack/types@7.4.1
- Updated dependencies [23c7107]
- Updated dependencies [c72daad]
- Updated dependencies [f115182]
- Updated dependencies [2faf9f2]
- Updated dependencies [2faf9f2]
- Updated dependencies [2faf9f2]
- Updated dependencies [58b450b]
- Updated dependencies [82eb6cf]
- Updated dependencies [13d8653]
- Updated dependencies [ff3d006]
- Updated dependencies [5e831de]
- @objectstack/spec@7.4.0
- @objectstack/core@7.4.0
- @objectstack/types@7.4.0
- Updated dependencies [5e7c554]
- @objectstack/spec@7.3.0
- @objectstack/core@7.3.0
- @objectstack/types@7.3.0
-
9096dfe:
OS_env-var prefix migration (issue #1382).All ObjectStack-owned environment variables now use the
OS_prefix. Legacy names still work for one release and emit a one-shot deprecation warning via the newreadEnvWithDeprecation()helper in@objectstack/types.Renamed (with legacy fallback):
New Legacy (deprecated) OS_AUTH_SECRETAUTH_SECRET,BETTER_AUTH_SECRETOS_AUTH_URLAUTH_BASE_URL,BETTER_AUTH_URL,OS_AUTH_BASE_URLOS_PORTPORTOS_DATABASE_URLDATABASE_URLOS_ROOT_DOMAINROOT_DOMAINOS_MULTI_ORG_ENABLEDOS_MULTI_TENANTOS_CORS_ENABLEDCORS_ENABLEDOS_CORS_ORIGINCORS_ORIGINOS_CORS_CREDENTIALSCORS_CREDENTIALSOS_CORS_MAX_AGECORS_MAX_AGEOS_AI_MODELAI_MODELOS_MCP_SERVER_ENABLEDMCP_SERVER_ENABLEDOS_MCP_SERVER_NAMEMCP_SERVER_NAMEOS_MCP_SERVER_TRANSPORTMCP_SERVER_TRANSPORTOS_NODE_IDOBJECTSTACK_NODE_IDOS_METADATA_WRITABLEOBJECTSTACK_METADATA_WRITABLEOS_DEV_CRYPTO_KEYOBJECTSTACK_DEV_CRYPTO_KEYOS_HOMEOBJECTSTACK_HOMEMigration: rename in your
.env. Legacy names continue to work this release and will be removed in a future major. Industry-standard names (NODE_ENV,HOME,OPENAI_API_KEY,TURSO_*, OAuth*_CLIENT_ID/SECRET,RESEND_API_KEY,POSTMARK_TOKEN,AI_GATEWAY_*,SMTP_*) are NOT renamed. -
Updated dependencies [9096dfe]
- @objectstack/types@7.2.1
- @objectstack/spec@7.2.1
- @objectstack/core@7.2.1
- @objectstack/spec@7.2.0
- @objectstack/core@7.2.0
- Updated dependencies [47a92f4]
- @objectstack/spec@7.1.0
- @objectstack/core@7.1.0
- Updated dependencies [74470ad]
- Updated dependencies [d29617e]
- Updated dependencies [dc72172]
- @objectstack/spec@7.0.0
- @objectstack/core@7.0.0
- @objectstack/spec@6.9.0
- @objectstack/core@6.9.0
- @objectstack/spec@6.8.1
- @objectstack/core@6.8.1
- Updated dependencies [6e88f77]
- Updated dependencies [c8b9f57]
- @objectstack/spec@6.8.0
- @objectstack/core@6.8.0
- @objectstack/spec@6.7.1
- @objectstack/core@6.7.1
- Updated dependencies [430067b]
- Updated dependencies [4f9e9d4]
- @objectstack/spec@6.7.0
- @objectstack/core@6.7.0
- Updated dependencies [a49cfc2]
- @objectstack/spec@6.6.0
- @objectstack/core@6.6.0
- @objectstack/spec@6.5.1
- @objectstack/core@6.5.1
- @objectstack/spec@6.5.0
- @objectstack/core@6.5.0
- Updated dependencies [f8651cc]
- Updated dependencies [f8651cc]
- Updated dependencies [0bf6f9a]
- @objectstack/spec@6.4.0
- @objectstack/core@6.4.0
- @objectstack/spec@6.3.0
- @objectstack/core@6.3.0
- Updated dependencies [b4c74a9]
- @objectstack/spec@6.2.0
- @objectstack/core@6.2.0
- @objectstack/spec@6.1.1
- @objectstack/core@6.1.1
- Updated dependencies [93c0589]
- @objectstack/spec@6.1.0
- @objectstack/core@6.1.0
- Updated dependencies [629a716]
- Updated dependencies [dbc4f7d]
- Updated dependencies [944f187]
- @objectstack/spec@6.0.0
- @objectstack/core@6.0.0
-
b806f58: Scope
sys_uservisibility to fellow organization members.The default RLS policy on
sys_userwasid = current_user.id, which meant @-mention pickers, owner/assignee lookups, reviewer selectors and the user roster all returned just the current user. The RLS compiler doesn't support subqueries, so aid IN (SELECT user_id FROM sys_member ...)policy isn't expressible.This change:
- Pre-resolves
org_user_ids(the IDs of all users in the active org) intoExecutionContextin all three REST entry-point resolvers (@objectstack/rest,@objectstack/runtime,@objectstack/plugin-hono-server). - Adds the field to
ExecutionContextSchemaso it survives Zod parsing. - Adds an
org_user_idsfield to the RLS compiler's user context. - Adds a new
sys_user_org_memberspolicy (id IN (current_user.org_user_ids)) to bothmember_defaultandviewer_readonlypermission sets, alongside the existingsys_user_selfpolicy. The RLS compiler OR-combines them, so users see themselves AND their org collaborators.
Capped at 1000 members per request. Large enterprises should plug in a directory cache or split per workspace.
- Pre-resolves
-
Updated dependencies [bab2b20]
-
Updated dependencies [fa011d8]
-
Updated dependencies [b806f58]
- @objectstack/spec@5.2.0
- @objectstack/core@5.2.0
- Updated dependencies [75f4ee6]
- Updated dependencies [823d559]
- @objectstack/spec@5.1.0
- @objectstack/core@5.1.0
- Updated dependencies [2f9073a]
- @objectstack/spec@5.0.0
- @objectstack/core@5.0.0
- Updated dependencies [2869891]
- @objectstack/spec@4.2.0
- @objectstack/core@4.2.0
- @objectstack/spec@4.1.1
- @objectstack/core@4.1.1
- Updated dependencies [2108c30]
- Updated dependencies [23db640]
- @objectstack/spec@4.1.0
- @objectstack/core@4.1.0
- 15e0df6: chore: unify all package versions to a single patch release
- Updated dependencies [15e0df6]
- @objectstack/spec@4.0.5
- @objectstack/core@4.0.5
- CORS middleware now exposes
set-auth-tokenby default so clients can capture rotated bearer tokens emitted by@objectstack/plugin-auth. HonoCorsOptionsacceptsallowHeadersandexposeHeaders. User-suppliedexposeHeadersare merged with theset-auth-tokendefault.
- Updated dependencies [326b66b]
- @objectstack/spec@4.0.4
- @objectstack/core@4.0.4
- @objectstack/spec@4.0.3
- @objectstack/core@4.0.3
- 5f659e9: fix ai
- Updated dependencies [5f659e9]
- @objectstack/spec@4.0.2
- @objectstack/core@4.0.2
- Updated dependencies [f08ffc3]
- Updated dependencies [e0b0a78]
- @objectstack/spec@4.0.0
- @objectstack/core@4.0.0
- @objectstack/spec@3.3.1
- @objectstack/core@3.3.1
- @objectstack/spec@3.3.0
- @objectstack/core@3.3.0
- 0bc7b0c: fix port confict
- @objectstack/spec@3.2.9
- @objectstack/core@3.2.9
- @objectstack/spec@3.2.8
- @objectstack/core@3.2.8
- @objectstack/spec@3.2.7
- @objectstack/core@3.2.7
- @objectstack/spec@3.2.6
- @objectstack/core@3.2.6
- @objectstack/spec@3.2.5
- @objectstack/core@3.2.5
- @objectstack/spec@3.2.4
- @objectstack/core@3.2.4
- @objectstack/spec@3.2.3
- @objectstack/core@3.2.3
- Updated dependencies [46defbb]
- @objectstack/spec@3.2.2
- @objectstack/core@3.2.2
- Updated dependencies [850b546]
- @objectstack/spec@3.2.1
- @objectstack/core@3.2.1
- Updated dependencies [5901c29]
- @objectstack/spec@3.2.0
- @objectstack/core@3.2.0
- Updated dependencies [953d667]
- @objectstack/spec@3.1.1
- @objectstack/core@3.1.1
- Updated dependencies [0088830]
- @objectstack/spec@3.1.0
- @objectstack/core@3.1.0
- Updated dependencies [92d9d99]
- @objectstack/spec@3.0.11
- @objectstack/core@3.0.11
- Updated dependencies [d1e5d31]
- @objectstack/spec@3.0.10
- @objectstack/core@3.0.10
- Updated dependencies [15e0df6]
- @objectstack/spec@3.0.9
- @objectstack/core@3.0.9
- Updated dependencies [5a968a2]
- @objectstack/spec@3.0.8
- @objectstack/core@3.0.8
- Updated dependencies [0119bd7]
- Updated dependencies [5426bdf]
- @objectstack/spec@3.0.7
- @objectstack/core@3.0.7
- Updated dependencies [5df254c]
- @objectstack/spec@3.0.6
- @objectstack/core@3.0.6
- Updated dependencies [23a4a68]
- @objectstack/spec@3.0.5
- @objectstack/core@3.0.5
- Updated dependencies [d738987]
- @objectstack/spec@3.0.4
- @objectstack/core@3.0.4
- c7267f6: Patch release for maintenance updates and improvements.
- Updated dependencies [c7267f6]
- @objectstack/spec@3.0.3
- @objectstack/core@3.0.3
- Updated dependencies [28985f5]
- @objectstack/spec@3.0.2
- @objectstack/core@3.0.2
- Updated dependencies [389725a]
- @objectstack/spec@3.0.1
- @objectstack/core@3.0.1
- Release v3.0.0 — unified version bump for all ObjectStack packages.
- Updated dependencies
- @objectstack/spec@3.0.0
- @objectstack/core@3.0.0
- Updated dependencies
- @objectstack/spec@2.0.7
- @objectstack/core@2.0.7
- Patch release for maintenance and stability improvements
- Updated dependencies
- @objectstack/spec@2.0.6
- @objectstack/core@2.0.6
- Updated dependencies
- @objectstack/spec@2.0.5
- @objectstack/core@2.0.5
- Patch release for maintenance and stability improvements
- Updated dependencies
- @objectstack/spec@2.0.4
- @objectstack/core@2.0.4
- Patch release for maintenance and stability improvements
- Updated dependencies
- @objectstack/spec@2.0.3
- @objectstack/core@2.0.3
- Updated dependencies [1db8559]
- @objectstack/spec@2.0.2
- @objectstack/core@2.0.2
- Patch release for maintenance and stability improvements
- Updated dependencies
- @objectstack/spec@2.0.1
- @objectstack/core@2.0.1
- Updated dependencies [38e5dd5]
- Updated dependencies [38e5dd5]
- @objectstack/spec@2.0.0
- @objectstack/core@2.0.0
- Updated dependencies
- @objectstack/spec@1.0.12
- @objectstack/core@1.0.12
- @objectstack/runtime@1.0.12
- @objectstack/types@1.0.12
- @objectstack/hono@1.0.12
- @objectstack/spec@1.0.11
- @objectstack/core@1.0.11
- @objectstack/types@1.0.11
- @objectstack/runtime@1.0.11
- @objectstack/hono@1.0.11
- Updated dependencies [10f52e1]
- @objectstack/core@1.0.10
- @objectstack/runtime@1.0.10
- @objectstack/hono@1.0.10
- @objectstack/spec@1.0.10
- @objectstack/types@1.0.10
- @objectstack/spec@1.0.9
- @objectstack/core@1.0.9
- @objectstack/types@1.0.9
- @objectstack/runtime@1.0.9
- @objectstack/hono@1.0.9
- 8f2a3a2: fix: standardize discovery endpoint response to include 'data' wrapper
- Updated dependencies [8f2a3a2]
- @objectstack/hono@1.0.8
- @objectstack/spec@1.0.8
- @objectstack/core@1.0.8
- @objectstack/types@1.0.8
- @objectstack/runtime@1.0.8
- ebdf787: feat: implement standard service discovery via
/.well-known/objectstack - Updated dependencies [ebdf787]
- @objectstack/runtime@1.0.7
- @objectstack/hono@1.0.7
- @objectstack/spec@1.0.7
- @objectstack/core@1.0.7
- @objectstack/types@1.0.7
- Updated dependencies [a7f7b9d]
- @objectstack/spec@1.0.6
- @objectstack/core@1.0.6
- @objectstack/runtime@1.0.6
- @objectstack/types@1.0.6
- @objectstack/hono@1.0.6
- b1d24bd: refactor: migrate build system from tsc to tsup for faster builds
- Replaced
tscwithtsup(using esbuild) across all packages - Added shared
tsup.config.tsin workspace root - Added
tsupas workspace dev dependency - significantly improved build performance
- Replaced
- 877b864: fix: add SPA fallback to hono, fix msw context binding, improve runtime resilience, and fix client-react build types
- Updated dependencies [b1d24bd]
- Updated dependencies [877b864]
- @objectstack/core@1.0.5
- @objectstack/runtime@1.0.5
- @objectstack/hono@1.0.5
- @objectstack/types@1.0.5
- @objectstack/spec@1.0.5
- 5d13533: refactor: fix service registration compatibility and improve logging
- plugin-hono-server: register 'http.server' service alias to match core requirements
- plugin-hono-server: fix console log to show the actual bound port instead of configured port
- plugin-hono-server: reduce log verbosity (moved non-essential logs to debug level)
- objectql: automatically register 'metadata', 'data', 'and 'auth' services during initialization to satisfy kernel contracts
- cli: fix race condition in
servecommand by awaiting plugin registration calls (kernel.use) - @objectstack/spec@1.0.4
- @objectstack/core@1.0.4
- @objectstack/types@1.0.4
- @objectstack/runtime@1.0.4
- @objectstack/hono@1.0.4
- 22a48f0: refactor: fix service registration compatibility and improve logging
- plugin-hono-server: register 'http.server' service alias to match core requirements
- plugin-hono-server: fix console log to show the actual bound port instead of configured port
- plugin-hono-server: reduce log verbosity (moved non-essential logs to debug level)
- objectql: automatically register 'metadata', 'data', 'and 'auth' services during initialization to satisfy kernel contracts
- Updated dependencies [fb2eabd]
- @objectstack/core@1.0.3
- @objectstack/runtime@1.0.3
- @objectstack/hono@1.0.3
- @objectstack/spec@1.0.3
- @objectstack/types@1.0.3
-
a0a6c85: Infrastructure and development tooling improvements
- Add changeset configuration for automated version management
- Add comprehensive GitHub Actions workflows (CI, CodeQL, linting, releases)
- Add development configuration files (.cursorrules, .github/prompts)
- Add documentation files (ARCHITECTURE.md, CONTRIBUTING.md, workflows docs)
- Update test script configuration in package.json
- Add @objectstack/cli to devDependencies for better development experience
-
109fc5b: Unified patch release to align all package versions.
-
Updated dependencies [a0a6c85]
-
Updated dependencies [109fc5b]
- @objectstack/spec@1.0.2
- @objectstack/core@1.0.2
- @objectstack/types@1.0.2
- @objectstack/runtime@1.0.2
- @objectstack/hono@1.0.2
- @objectstack/spec@1.0.1
- @objectstack/core@1.0.1
- @objectstack/types@1.0.1
- Major version release for ObjectStack Protocol v1.0.
- Stabilized Protocol Definitions
- Enhanced Runtime Plugin Support
- Fixed Type Compliance across Monorepo
- Updated dependencies
- @objectstack/spec@1.0.0
- @objectstack/core@1.0.0
- @objectstack/types@1.0.0
- Updated dependencies
- @objectstack/spec@0.9.2
- @objectstack/core@0.9.2
- @objectstack/types@0.9.2
- Patch release for maintenance and stability improvements. All packages updated with unified versioning.
- Updated dependencies
- @objectstack/spec@0.9.1
- @objectstack/core@0.9.1
- @objectstack/types@0.9.1
- Updated dependencies [555e6a7]
- @objectstack/spec@0.8.2
- @objectstack/core@0.8.2
- @objectstack/types@0.8.2
- @objectstack/spec@0.8.1
- @objectstack/core@0.8.1
- @objectstack/types@0.8.1
-
This release includes a major upgrade to the core validation engine (Zod v4) and aligns all protocol definitions with stricter type safety.
- Updated dependencies
- @objectstack/spec@1.0.0
- @objectstack/core@1.0.0
- @objectstack/types@1.0.0
- fb41cc0: Patch release: Updated documentation and JSON schemas
- Updated dependencies [fb41cc0]
- @objectstack/spec@0.7.2
- @objectstack/core@0.7.2
- @objectstack/types@0.7.2
- Patch release for maintenance and stability improvements
- Updated dependencies
- @objectstack/spec@0.7.1
- @objectstack/types@0.7.1
- @objectstack/core@0.7.1
- Patch release for maintenance and stability improvements
- Updated dependencies
- @objectstack/spec@0.6.1
- @objectstack/types@0.6.1
- @objectstack/core@0.6.1
-
b2df5f7: Unified version bump to 0.5.0
- Standardized all package versions to 0.5.0 across the monorepo
- Fixed driver-memory package.json paths for proper module resolution
- Ensured all packages are in sync for the 0.5.0 release
- Updated dependencies [b2df5f7]
- @objectstack/spec@0.6.0
- @objectstack/types@0.6.0
- @objectstack/core@0.6.0
- Unify all package versions to 0.4.2
- Updated dependencies
- @objectstack/spec@0.4.2
- @objectstack/runtime@0.4.2
- @objectstack/types@0.4.2
-
Version synchronization and dependency updates
- Synchronized all plugin versions to 0.4.1
- Updated runtime peer dependency versions to ^0.4.1
- Fixed internal dependency version mismatches
-
Updated dependencies
- @objectstack/spec@0.4.1
- @objectstack/types@0.4.1
- @objectstack/runtime@0.4.1
- Release version 0.4.0
-
Workflow and configuration improvements
- Enhanced GitHub workflows for CI, release, and PR automation
- Added comprehensive prompt templates for different protocol areas
- Improved project documentation and automation guides
- Updated changeset configuration
- Added cursor rules for better development experience
-
Updated dependencies
- @objectstack/spec@0.3.3
- @objectstack/runtime@0.3.3
- @objectstack/types@0.3.3
- Patch release for maintenance and stability improvements
- Updated dependencies
- @objectstack/runtime@0.3.2
- @objectstack/spec@0.3.2
- @objectstack/types@0.3.2
- Updated dependencies
- @objectstack/runtime@0.3.1
- @objectstack/spec@0.3.1
- @objectstack/types@0.3.1
- Updated dependencies
- @objectstack/spec@1.0.0
- @objectstack/runtime@1.0.0
- @objectstack/types@1.0.0
-
Initial release of ObjectStack Protocol & Specification packages
This is the first public release of the ObjectStack ecosystem, providing:
- Core protocol definitions and TypeScript types
- ObjectQL query language and runtime
- Memory driver for in-memory data storage
- Client library for interacting with ObjectStack
- Hono server plugin for REST API endpoints
- Complete JSON schema generation for all specifications
- Updated dependencies
- @objectstack/spec@0.2.0
- @objectstack/types@0.2.0
- @objectstack/runtime@0.2.0
- Remove debug logs from registry and protocol modules
- Updated dependencies
- @objectstack/spec@0.1.2
- @objectstack/runtime@0.1.1
- @objectstack/types@0.1.1