fix(seed): bind seed records to users via os.user + fail loudly on unresolved refs#1392
Conversation
…resolved refs Fixes #1389. Seed records can now bind to a platform user with `cel`os.user.id`` (and to the org with `cel`os.org.id``), which previously never resolved at boot — making objects with a required lookup('user') un-seedable, and silently dropping the records. - Resolve os.user / os.org: thread a new SeedLoaderConfig.identity through the CEL eval context in the seed loader (os.org falls back to organizationId). - Deterministic seed owner: AppPlugin provisions a non-loginable system user (usr_system, role `system`) before any seed runs and binds it as os.user, so identity-derived seeds resolve on a fresh boot — before the first human sign-up. The better-auth login admin stays separate (ADR-0010 respected). Exposed as SystemUserId.SYSTEM. - Loud failures: unresolved CEL values and write failures are now counted as errors (result.success === false) with actionable messages, instead of being silently dropped — in both the inline run and the per-tenant replayer. - Docs: seed-data guide documents the os.user binding, the usr_system ordering guarantee, and the loud-failure behavior. Tests: 4 new seed-identity cases; full runtime suite 307 passing.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
CI diagnosis — both failures are pre-existing on
|
…n@objectos.ai bootstrapPlatformAdmin promoted the earliest-created sys_user, but #1392 (ensureSeedIdentity) provisions a non-loginable system identity (usr_system, role 'system') before the first human sign-up to own seeded rows. On any app shipping seed data it won the promotion, leaving the real admin at role:user — login worked but Setup/Studio (gated by setup.access / studio.access on admin_full_access) stayed invisible. - bootstrap-platform-admin.ts: exclude the system account (id === SystemUserId.SYSTEM || role === 'system') when selecting the first user; the "admin already exists" check ignores any admin_full_access grant held by usr_system, so a wrongly-promoted DB self-heals on reboot. - cli/dev.ts: --admin-email / --admin-password defaults change from admin@dev.local / admin12345 to fixed admin@objectos.ai / admin123. - Docs/skill: AGENTS.md, security.mdx, objectstack-platform SKILL.md, CHANGELOG.md + changeset updated to the new creds and the human-first promotion rule. Verified: pnpm dev → seeded admin get-session resolves role:admin and the cross-tenant admin_full_access grant belongs to the human admin.
Summary
Fixes #1389 — "Seed data: no way to bind records to users (required
lookup('user')makes objects un-seedable, fails silently)".Records seeded via
defineDataset/defineStack({ data })can now bind to a platform user withcel`os.user.id`(and to the org withcel`os.org.id`). Previously this never resolved at boot, so any object with a required owner lookup was un-seedable and the records were silently dropped.What changed
1.
os.user/os.orgnow resolve (first-class binding)SeedLoaderConfig.identity(@objectstack/spec) carries theos.user/os.orgsubject into CEL evaluation.os.orgfalls back toorganizationIdwhen not explicitly set.os.user/os.org— no new syntax (currentUser(),@admin, …).2. Admin availability / ordering guarantee
AppPluginprovisions a deterministic, non-loginable system user (usr_system, rolesystem) before any seed runs and binds it asos.user, so identity-derived seeds resolve even on a fresh boot — before the first human sign-up.sys_userrespected — no credential is minted here). Analogous to Salesforce's "Automated Process" user.SystemUserId.SYSTEMconstant.3. Loud failure instead of silent drop
cel`os.user.id`with no identity) — or that fails to write — is now counted as an error, marks the loadsuccess === false, and logs an actionable message.4. Docs
content/docs/guides/seed-data.mdxgains a "Dynamic Values (CEL)" section covering theos.userbinding, theusr_systemordering guarantee, and the loud-failure behavior.Reviewer notes
minorfor@objectstack/spec+@objectstack/runtime) is included.@objectstack/specmust be rebuilt so itsdist.d.tsexposes the newidentityfield +SystemUserId(vitest resolves spec from src, buttscresolves via dist).Testing
os.user.id; loud failure when unbound;os.org→organizationIdfallback; write-failure surfaced).tsc --noEmitclean on bothruntimeandspec.