Skip to content

Delete the pnpm demo priming boot once the platform mints the dev admin alongside a seeded user table #131

Closed

Description

@os-warren

Part of #127 (A — remove the demo scaffolding).

Blocked on a release carrying objectstack-ai/objectstack#25830 (see the Release comment; the earlier unblock reading was wrong). 2026-10-26T07:18Z

Why

scripts/demo.mjs boots twice: once with the seed off so @objectstack/plugin-auth mints the dev admin on a zero-user database, then again with the seed on. The whole priming step, its sign-in probe, its process-group teardown and (since #117) the admin rename exist only because plugin-auth's "any human row exists" check skips the admin when the seed carries users — objectstack#14157. A template should be one boot.

What "done" is

When objectstack#14157 is fixed and released in a @objectstack/* version this app can install (the unlock criterion is "consumer can install", not "merged"):

  1. Bump to that version; delete the priming boot from scripts/demo.mjs so pnpm demo and pnpm demo:zh are a single objectstack dev --compile spawn with the env set. Keep the zh-CN admin rename only if the platform fix still leaves the admin named Dev Admin — measure, do not assume.
  2. src/data/index.ts and src/data/demo-org.ts header comments that explain the two-boot sequencing are rewritten to describe the one-boot reality.
  3. test/demo-script.test.ts updated; both demos boot on a clean database and sign in (POST /api/v1/auth/sign-in/email → 200) — evidence in the PR.

Restart-when: npm view @objectstack/plugin-auth version names a release whose changelog or source carries the #14157 fix (verify by reading the installed maybeSeedDevAdmin), then move this card to pm:ready.

Activity

  1. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    Unlock re-check (duly lane seat, session session_011HyoSXGRy6L13mYq1Hp4n1, 2026-10-26T06:32Z): Restart-when satisfied — moving to pm:ready.

    Serial note for whoever claims it: scripts/demo.mjs and the src/data/* header comments are shared with #132 and #134; this card queues behind #132 in the lane's hot-file order.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 1
    Session: session_011HyoSXGRy6L13mYq1Hp4n1
    Account: os-warren (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/project-thread-0vbnu9 (platform-assigned card-thread branch; the card thread may push only this branch)
    Worktree: duly-issue-131
    Domain: n/a — objectstack-ai/duly is a single-lane app repo (no domain:*); the duly lane seat does first-touch itself
    Seat: repo:duly#1
    File surface: scripts/demo.mjs, the two-boot header comments in src/data/index.ts and src/data/demo-org.ts, test/demo-script.test.ts (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: TIER_DEFAULT (hand-derived: dispatch-gates answers only objectstack's tree), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6409799615
    Premise: holds (unlock reading in comment 6409799615; the single-boot behaviour itself is the dev's first measurement)
    Serial constraints cleared: #132 (claude/project-thread-oaj047) claimed README.md and docs/** and excluded scripts/demo.mjs and src/data/**, so the surfaces are disjoint; #134 queues behind this card on demo wiring

    Triage (first touch, 2026-10-26T06:59Z): lands in objectstack-ai/duly; rationale: epic #127 A item (remove the demo scaffolding), maintainer ruling quoted in the epic body; type Task; ungraded (no priority:p2 label in this repo yet).


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 131,
    "status": "blocked",
    "branch": "claude/project-thread-0vbnu9",
    "pr": null,
    "session": "session_01ReJaAa5Znivr1Eu8xA8Ais",
    "premise_still_valid": false,
    "summary": "Hypothesis (1) holds as stated: on @objectstack/plugin-auth 17.3.0 one objectstack dev --compile boot with DULY_DEMO_SEED=1 on a clean DB mints the dev admin and POST /api/v1/auth/sign-in/email answers 200 (13.9s from spawn). The card premise does not: the priming boot exists for TWO reasons, and objectstack-ai/objectstack#14157 removed only one. The admin is still minted on kernel:ready, AFTER the declarative seed, so the seed's name-only ADMIN sys_user row is INSERTED first and signUpEmail then creates a second, separate row; result on the one-boot path is 14 sys_user rows, two named Dev Admin, and the demo account's own work (23 duly_task.owner, 6 duly_duty.owner, 8 duly_log_entry.owner, 1 duly_assignment.assigner) belongs to the credential-less ghost row, so My week / My duties / Sent by me / Work log are empty for the account you sign in as. That is the silent failure test/demo-script.test.ts and the demo-org.ts header exist to prevent, so deleting the priming boot would trade a visible two-step for an invisible broken demo; no PR was opened and no file was edited. The in-surface workaround (seed row carries admin@objectos.ai so the mint lands on it) is worse: signUpEmail answers 'User already exists', no sys_account row is written, sign-in 401 for 240s. Control leg: today's two-boot pnpm demo on the same 17.3.0 install gives 13 users, one Dev Admin with the credential, owning all 23/6/8/1 rows. Hypothesis (2): the PATCH rename is replaceable, not removable: 17.3.0 maybeSeedDevAdmin reads OS_SEED_ADMIN_NAME (one boot with OS_SEED_ADMIN_NAME=演示管理员 mints the account under that name, sign-in 200), but it hits the same ghost-row split (two rows named 演示管理员). The upstream fix for the ordering is objectstack-ai/objectstack#25830 (demoStaff; with demoStaff declared the dev boot defers the app seed to kernel:bootstrapped, after the admin and demo accounts are minted), merged to objectstack main on 2026-10-26, not in any published version (latest @objectstack/plugin-auth is 18.1.0, published before the merge), and 18.x is out of this card by order.",
    "tests": "No code changed, so no test run is owed. Measurement harness (scratchpad measure.mjs + db.cjs, copied to the project folder duly-131-oneboot) on a detached worktree at origin/main 004380e, each run after rm -rf .objectstack dist: en-oneboot (DULY_DEMO_SEED=1): sign-in 200, user Dev Admin admin@objectos.ai; sqlite: users 14, admin-ish rows [Dev Admin email null] + [Dev Admin admin@objectos.ai], sys_account 1 credential on the minted id; duly_task.owner on the null-email row n=23, duly_duty.owner n=6, duly_log_entry.owner n=8, duly_assignment.assigner n=1. Boot log carries ERROR [auth] no_sign_in_account_at_boot at seed time, then 'Dev admin: admin@objectos.ai / admin123 seeded on empty DB'. en-seedemail (org.seed.ts ADMIN row given email admin@objectos.ai, uncommitted, restored with git checkout HEAD and git diff HEAD empty): WARN [auth] dev admin seed skipped: User already exists. Use another email; sys_account 0 rows; sign-in 401 INVALID_EMAIL_OR_PASSWORD through 240s. zh-oneboot-envname (DULY_DEMO_LOCALE=zh-CN, OS_SEED_ADMIN_NAME=演示管理员): sign-in 200 as 演示管理员; users 14, two rows named 演示管理员, owner rows on the null-email one (23/6/8/1). zh-oneboot-plain (no name env): sign-in 200 as Dev Admin; ghost row 演示管理员 owns 23/6/8/1. control-twoboot (current scripts/demo.mjs unchanged): '1/2 done - admin account ready', Seeds 443 rows, sign-in 200, users 13, one Dev Admin with credential owning 23/6/8/1. Ablation: n/a, no tested behaviour changed.",
    "gates": "NOT MEASURED: pnpm validate / typecheck / test / build, reason: no diff (premise falsified before the first edit). pnpm demo and pnpm demo:zh single-boot gates replaced by the measurement above, which is the card's own acceptance question. dispatch-gates.mjs not run: it answers only objectstack's tree and there is no duly diff.",
    "dogfood_battery": "n/a - no PR",
    "mcp_calls": "0",
    "api_writes": "1 - POST /repos//issues/131/comments (this os-dev-report, via post-stamped.mjs and the fleet-write relay). Reads were unauthenticated public REST GETs of issue 131 and its comments.",
    "open_questions": [
    {
    "question": "How should #131 proceed now that one boot logs in but hands the demo account's work to a ghost user?",
    "options": [
    "A - Re-block #131 on a published @objectstack release carrying objectstack-ai/objectstack#25830 (demoStaff + seed deferred past the admin mint), and widen the card to include the 18.x bump; new Restart-when: npm view @objectstack/plugin-auth names a version whose dist defers the app seed when demoStaff is declared, verified by one clean-DB boot showing 13 users and the admin owning its 23 tasks. Cost: waits on an upstream release plus an 18.x major bump (its own validation work).",
    "B - Keep the two-boot script as the permanent design, mark this card not planned, and optionally simplify the zh-CN rename to OS_SEED_ADMIN_NAME on the priming boot (drops the PATCH and its re-sign-in check; small, about 60 lines out of scripts/demo.mjs). Cost: the template keeps a two-step demo.",
    "C - File an upstream card asking 17.x maybeSeedDevAdmin to adopt a credential-less sys_user row that matches the seed address or name instead of minting a second row. Cost: an extra platform contract that objectstack-ai/objectstack#25830 already supersedes on 18.x."
    ],
    "recommendation": "A, because objectstack-ai/objectstack#25830 is the platform's declared answer to exactly this ordering (ruling: demo accounts are the platform's to create; the app only declares them), it would also make the twelve demo people loginable, and the duly change then really is one spawn. B's OS_SEED_ADMIN_NAME simplification is worth taking meanwhile only if the seat wants the zh path shorter before 18.x."
    }
    ],
    "out_of_scope_findings": [
    "carrier: objectstack-ai/objectstack#25830 (merged, unreleased) - plugin-auth 17.3.0 maybeSeedDevAdmin mints a second sys_user row when the app seed already holds a credential-less row with the same name; the deferred-seed path in objectstack-ai/objectstack#25830 is the fix. Noted, not filed.",
    "carrier: none - on the one-boot path the boot log prints ERROR [auth] no_sign_in_account_at_boot (NOBODY CAN SIGN IN ... CANNOT BE RECOVERED FROM INSIDE) a few hundred ms before the same boot mints a loginable admin; reach: only on the hypothetical one-boot demo, the shipped two-boot script never shows it, so recorded here only (Acceptance-notes class)."
    ]
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    Release: session session_011HyoSXGRy6L13mYq1Hp4n1 (duly lane seat) releases its claim (comment 6410182398) at 2026-10-26T07:17Z · cause: premise disproved · destination: pm:on-hold, assignee cleared.

    Correction, in public: my unlock reading (comment 6409799615) was wrong. I read that 17.3.0 gates the dev-admin seed on the credential store and concluded the priming boot could go. The card thread measured the boot itself (report 6410423085): on one objectstack dev --compile boot the admin is minted and sign-in answers 200, but kernel:ready still runs after the seed, so the seed's name-only admin row lands first and sign-up creates a second one — 14 users, two "Dev Admin", and every row the demo gives the admin belongs to the credential-less ghost, so the account you sign in as sees an empty week. Today's two-boot script on 17.3.0 is correct (13 users, the admin owns its rows). So the gate fix was necessary and not sufficient; the card's own "measure, do not assume" caught it. ACCEPT of the report: premise false, no PR, no edits — a first-class result.

    The fix that does make it one boot is objectstack-ai/objectstack#25830 (demoStaff, seed deferred to kernel:bootstrapped), merged 2026-10-26. It is not in any installable release yet: @objectstack/plugin-auth dist-tags latest 18.1.0 (published 2026-10-24) predates it.

    Restart-when: npm view @objectstack/plugin-auth version names a release published after 2026-10-26T04:03Z whose installed dist carries demoStaff (grep -c demoStaff node_modules/@objectstack/plugin-auth/dist/index.js ≥ 1; positive control maybeSeedDevAdmin must also hit), and this repo is on that release line (#139 lands the 18.x bump first).

    When it restarts, the card widens per the report's option A: declare the demo accounts with demoStaff and drop the priming boot in the same PR; OS_SEED_ADMIN_NAME replaces the zh-CN rename.


    Generated by Claude Code

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    Contributor

    Unblocked at 2026-11-02T02:21Z. The restart condition holds on both legs. @objectstack/plugin-auth 18.2.0 carries demoStaff (CHANGELOG 18.2.0, change f00e8d5: "an application declares the demo accounts its seed data is dealt to, and the development boot creates them", which is objectstack#25830). duly main (25743ed) runs ^18.2.0. Moved from pm:on-hold to pm:ready. Widen per option A, as recorded earlier on this card.

    Queue note: #128 goes first, because it also rewrites demo rows. This card follows it, since both edit src/data/demo-org.ts, src/data/org.seed.ts and scripts/demo.mjs. #154 now grants the admin its Duly sets in src/data/org.seed.ts; keep that grant, or carry it into demoStaff's permissionSets if the admin becomes a declared entry.


    Generated by Claude Code

  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 4
    Session: session_011HyoSXGRy6L13mYq1Hp4n1
    Account: os-warren (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-l80jai (platform-assigned card-thread branch, at origin/main 3834578)
    Worktree: duly-issue-131
    Domain: n/a. objectstack-ai/duly is a single-lane app repo with no domain:*.
    Seat: repo:duly#1
    File surface: scripts/demo.mjs, src/data/demo-org.ts, src/data/org.seed.ts (comments only), src/data/index.ts, src/data/demo-staff.ts (new), test/demo-script.test.ts, test/demo-staff.test.ts (new, optional), the demo lines of README.md, and one line in objectstack.config.ts: the demoStaff key pointing at a named export of the src/data/index.ts barrel. The config line is a seat-granted exception to AGENTS.md rule 2: demoStaff is a top-level defineStack envelope key that no barrel feeds, and no other open card touches the config. Nothing else in the config moves. Stop on any breach until the seat posts a Claim amendment.
    Container & model: M, mode:thread, model: TIER_DEFAULT (hand-derived), effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: Make pnpm demo and pnpm demo:zh a single objectstack dev --compile spawn by seeding the demo people as plugin-auth 18.2.0 demoStaff, with the dev admin kept outside that list; measure whether the zh-CN admin rename is still needed.
    Thread-read: 6567530995
    Premise: The card thread read installed plugin-auth 18.2.0: maybeSeedDevAdmin alone still has the 17.3 shape, and the unlock is AppPlugin deferring the inline seed when the demo-staff service is armed by a non-empty top-level demoStaff on a dev loopback boot.
    Serial constraints cleared: #134 (pack format, shares the demo data) is held until this lands; #147 and #162 claim object, action, translation and test files outside this surface.


    Generated by Claude Code

  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    Contributor

    Claim amendment (duly lane seat, session session_011HyoSXGRy6L13mYq1Hp4n1, 2026-11-02T03:50Z).


    Generated by Claude Code

  8. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    Contributor

    Claim amendment 2 (duly lane seat, session session_011HyoSXGRy6L13mYq1Hp4n1, 2026-11-02T03:54Z).

    • Added to the file surface: src/translations/authored-text.ts, one line in COLLECTION_HANDLING next to data:. It classifies the new demoStaff key as data, not authored labels. Without it, test/i18n-coverage.test.ts fails ("every metadata collection in the config is either walked or declared text-free").
    • No other change in that file. No other open card touches it.
    • Everything else in the Claim and amendment 1 stands.

    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions