Skip to content

feat(spec,objectql): unify developer-facing org identifier in hooks — organizationId is blessed (#3280)#3284

Merged
os-zhuang merged 2 commits into
mainfrom
feat/unify-org-identifier
Jul 19, 2026
Merged

feat(spec,objectql): unify developer-facing org identifier in hooks — organizationId is blessed (#3280)#3284
os-zhuang merged 2 commits into
mainfrom
feat/unify-org-identifier

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #3280.

Problem

The caller's active organization was surfaced to third-party hook authors as ctx.session.tenantId, while everything else on the developer surface — the organization_id column, current_user.organizationId (RLS/sharing), and seed rows — already said organization. A developer had to internalize the hidden equation tenantId === organizationId to move between authoring modes. The ergonomic ctx.user shortcut had no org field at all, forcing hook authors onto session.tenantId.

Change — additive, non-breaking

  • ctx.session.organizationId added as the blessed name; ctx.session.tenantId kept as a @deprecated alias carrying the identical value. Both come from the resolved ExecutionContext.tenantId (kernel-derived from session.activeOrganizationId).
  • ctx.user.organizationId added to the ergonomic user shortcut. The engine now populates ctx.user ({ id, email?, organizationId? }) at every hook event that already carries a session (before/after find/insert/update/delete); it stays undefined for system / unauthenticated writes.
  • Hook-authoring docs teach organizationId and add a note distinguishing the two isolation axes: org row-scoping (organization_id, shared DB) vs environment / database-per-tenant (service-tenant, driver-turso).

Non-goals (untouched, per the issue)

The generic driver-layer tenancy abstraction — ExecutionContext.tenantId, DriverOptions.tenantId, SqlDriver.applyTenantScope, TenancyConfig.tenantField — is deliberately left as-is. That layer's isolation column is configurable and legitimately carries an environment id in database-per-tenant kernels; renaming it would bake an "org" assumption into a generic layer and be a wide public-API break.

Acceptance criteria

  • ctx.user.organizationId available in JS hooks (all events that populate session), typed in HookContext (spec).
  • ctx.session.organizationId available; ctx.session.tenantId still works, marked deprecated in TSDoc.
  • Both fields always equal execCtx.tenantId — unit tests cover a populated org, the unscoped/no-org case, and the system/no-user case.
  • Hook authoring docs/examples updated to organizationId.
  • Note distinguishing the two isolation axes (in skills/objectstack-data/references/data-hooks.md).
  • No behavior change, no breaking rename; changeset added (@objectstack/spec + @objectstack/objectql, patch).

Verification

  • @objectstack/spec tsc --noEmit ✓; full spec suite 6765 passed.
  • @objectstack/objectql DTS build ✓; full engine suite 955 passed (incl. 3 new #3280 tests).
  • @objectstack/runtime sandbox body-runner 11 passed (L2 JS hooks now receive the populated ctx.user).
  • Drift/lint gates green: check:docs (regenerated hook.mdx), check:skill-refs, check:skill-docs, check:doc-authoring, check:api-surface, check:spec-changes, check:role-word, check:nul-bytes; downstream-contract typecheck.

🤖 Generated with Claude Code

os-zhuang and others added 2 commits July 18, 2026 22:38
feat(evaluator): route CEL-dialect component/action predicates to the canonical engine (#2664)

objectui@2e7d7f0f7ee76b838f580e8a36b74f1309b204fc
… organizationId is blessed (#3280)

The caller's active organization was surfaced to hook authors as
`ctx.session.tenantId`, while the column (`organization_id`), RLS
(`current_user.organizationId`), and seed rows already said `organization`.
A hook author had to internalize `tenantId === organizationId` to move
between surfaces.

Additive, non-breaking:
- `ctx.session.organizationId` added as the blessed name; `session.tenantId`
  kept as a deprecated alias with the identical value (both from
  `ExecutionContext.tenantId`, resolved from `session.activeOrganizationId`).
- `ctx.user.organizationId` added to the ergonomic user shortcut; the engine
  now populates `ctx.user` at every hook event that carries a session, and it
  stays undefined for system/unauthenticated writes.

Generic driver-layer tenancy (`ExecutionContext.tenantId`,
`DriverOptions.tenantId`, `SqlDriver.applyTenantScope`,
`TenancyConfig.tenantField`) is deliberately untouched — that layer's
isolation column is configurable and can carry an environment id in
database-per-tenant kernels. Docs now teach `organizationId` and distinguish
the two isolation axes (org row-scoping vs environment/database-per-tenant).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 19, 2026 2:04pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation protocol:data tests tooling size/m labels Jul 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/objectql, @objectstack/spec.

107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/objectql, packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via packages/objectql, @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/migration-from-objectql.mdx (via @objectstack/objectql)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/vercel.mdx (via @objectstack/objectql)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/objectql, @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/objectql)
  • content/docs/permissions/authentication.mdx (via @objectstack/objectql)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/objectql, @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/objectql, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/objectql, @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/objectql, @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/objectql, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/objectql, @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:data size/m tests tooling

Projects

None yet

1 participant