Skip to content

chore(examples): let one example app boot under a walled posture — declare @objectstack/organizations (loaded only when OS_TENANCY_POSTURE is group or isolated), so a walled os serve can be measured without a temporary edit #25365

Closed

Description

@objectstack-fleet

Filing gate ③: an observation reported by three epic dev sessions (#25271, #24446 U1, #24446 U2). The maintainer asked why the example apps need the package; the answer is in this card.

  • Who acts: the shared queue.
  • Dedupe: none.

What is on main

  • @objectstack/organizations is the multi-organization runtime: the organization_id auto-stamp, per-organization seed replay, and the org-scoping service SecurityPlugin probes.
    • os serve loads it only when the posture is walled (packages/cli/src/commands/serve.ts, multiTenant = tenancyPosture !== 'single').
    • Under a walled posture without it, the boot refuses (unless OS_ALLOW_DEGRADED_TENANCY).
    • Under single, the default, it is never loaded.
  • It is app-declared on purpose (ADR-0132 D3, one name and two packages): the framework publishes the Apache-2.0 build, a commercial deployment resolves the same name to its own build, and the host manifest decides which.
  • No app under examples/ declares it. So every walled R4 measurement (a production os serve under isolated and group) has had to add it temporarily and restore it after.
  • U2's R4 also had to set, temporarily:
    • a membership policy (OS_AUTH_MEMBERSHIP_POLICY);
    • an OS_SECRET_KEY;
    • for a self-registering tenant, an audience posture with its self-registration set.

Wanted

  • Pick one, after measuring:
    • (a) one example (the showcase, say) declares the open build, so single is unaffected because it is never loaded there; or
    • (b) a dedicated walled fixture under packages/qa/dogfood that declares it.
  • Document the walled os serve recipe next to it: the env a walled production boot needs.

Acceptance

  • A walled production os serve of the chosen app or fixture boots under isolated and group with no temporary edit, pinned or scripted.
  • single boots of every example are unchanged.

Activity

  1. added
    domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they land
    on Oct 23, 2026
  2. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop · domain:cli seat 1 · p3 · 2026-10-23T11:40Z
    Session: session_01CxBKycaiUpA1yGx1XyoGqX
    Account: os-sales (the seat's linked user; always the card's assignee)
    Branch: claude/issue-25365-walled-example
    Worktree: objectstack-issue-25365
    Domain: domain:cli
    Seat: domain:cli#1 (seat post #6024; 由Sales账户的项目负责)
    File surface (read on origin/main 830a63a680; stop on a breach and explain it in the report): one example app's manifest under examples/app-showcase/ (its package.json dependency and, if needed, its stack config) to declare @objectstack/organizations, OR a walled fixture under packages/qa/dogfood/, whichever the dev measures as the card's option (a) or (b); plus its README / one docs line naming how to boot it walled, and the lockfile the dependency adds.
    Container & model: S, mode:subagent, model: default tier
    Clause-②: no
    Basis for the Clause-② line: an example's own dependency declaration; no accept set or public surface moves.
    Responsibility: n/a — not a product defect card (a measurement convenience, filing gate ③).
    Thread-read: none
    Serial constraints cleared: none — no open PR touches examples/app-showcase/** or @objectstack/organizations (the 12 open PRs' file lists read in this act).

  3. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 25365,
      "status": "done",
      "branch": "claude/issue-25365-walled-example",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/25418",
      "session": "session_01CxBKycaiUpA1yGx1XyoGqX",
      "premise_still_valid": true,
      "summary": "Option (a): examples/app-showcase/package.json declares @objectstack/organizations (workspace:*, the open build); pnpm-lock.yaml gains only that importer link (+3); the showcase README gains a 'Booting it walled' section with the production env recipe. All three PM mechanism assumptions verified on origin/main 830a63a680 (serve.ts: multiTenant = tenancyPosture !== 'single', importFromHost from the served app, walled absence exits 1 unless OS_ALLOW_DEGRADED_TENANCY). Walled production boots now pass under isolated and group with env only; single is byte-identical in its plugin list with and without the package present. The recipe needs three env vars the card did not list: OS_PLATFORM_OWNER_EMAIL (walled auth refusal), plus OS_AUTH_SECRET and OS_DATABASE_URL (any production serve); each was measured as its own boot refusal.",
      "tests": "Boots at head 0cc7b77e12, NODE_ENV=production, fresh DB, OS_CLOUD_URL=off, common env OS_AUTH_SECRET + OS_SECRET_KEY + OS_DATABASE_URL=file:./.objectstack/data/app.db: single :: ready (exit 0 on SIGTERM), 'Tenancy: single', 'Plugins: 50 loaded', no Organizations, /auth/config multiOrgEnabled:false | single with the package link removed (control) :: ready, plugin list md5 identical (f0a4cc42...) | isolated README recipe verbatim (pnpm exec objectstack serve, + OS_PLATFORM_OWNER_EMAIL + OS_AUTH_MEMBERSHIP_POLICY=invite-only) :: ready, 'Tenancy: isolated', 'Plugins: 51 loaded', Organizations listed, degradedTenancy:false | group same :: ready, 'Tenancy: group', 51 plugins, Organizations, degradedTenancy:false | isolated with package link removed (control) :: exit 1 'FATAL: tenancy posture isolated was requested but @objectstack/organizations could not be loaded' | isolated without membership policy :: exit 1 'FATAL: ... walled, but this deployment never declared a membership policy' | isolated without OS_SECRET_KEY :: exit 1 '[LocalCryptoProvider] Refusing to start in production without a stable encryption key' | isolated without OS_PLATFORM_OWNER_EMAIL :: exit 1 'requires OS_PLATFORM_OWNER_EMAIL to be set'. pnpm --filter @objectstack/example-showcase run typecheck && run test :: VERDICT command-exit 0, Test Files 37 passed (37), Tests 443 passed (443). No ablation: no tested behaviour changed (manifest, lockfile, docs).",
      "gates": "head 0cc7b77e12. Build closure: os-verify-lock pnpm --workspace-concurrency=2 --filter '@objectstack/example-showcase^...' build :: VERDICT command-exit 0. dispatch-gates --commands: 47 commands, 46 :: exit 0, pnpm check:dual-build-cjs-loads :: exit 3 (PREREQUISITE NOT MET, no dist for 7 packages outside the closure) = NOT MEASURED: dual-build-cjs-loads, reason: needs a full workspace build; CI runs it. --ran reconciliation with exit codes: '47 derived, 46 run, 1 NOT-MEASURED, 0 UNRUN'. pnpm lint (os-verify-lock) :: VERDICT command-exit 0. check:nul-bytes :: exit 0. PR check-runs: in_progress at report time (not waited on, per contract). NOT MEASURED locally: CI-scheduled Test Core / Build Core / Build Docs jobs and the type-check lanes, reason: CI-owned.",
      "dogfood_battery": "n/a — no ! in the PR title and Clause-②: no without a (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "3 — git push (branch, 3 pushes, not REST); fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/pulls + POST /issues/25418/assignees + POST /issues/25418/labels, one stroke, read-back identical 4115/4115 bytes, labels skip-changeset and assignee os-sales read back); post-stamped comment POST /repos/objectstack-ai/objectstack/issues/25365/comments (this report)",
      "line_budget": "S: +30 / -0 across 3 files (README +26, package.json +1, pnpm-lock.yaml +3)",
      "files_changed": [
        "examples/app-showcase/package.json",
        "examples/app-showcase/README.md",
        "pnpm-lock.yaml"
      ],
      "deviations": [
        "PR body: the dispatch asked for the attribution comment + Requested-by line as the first two lines and an ending with the robot-emoji 'Generated with' line plus the session URL; the role file wants Fixes as the first line and the session-URL footer form. Kept the dispatch's two head lines (read back byte-identical, nothing eaten), put Fixes #25365 on line 4, and ended with the role file / AGENTS.md session-URL footer form instead of the dispatch's ending, since the role file wins on conflict.",
        "Boot measurements were taken outside the verify lock (dev-server class, per the role file); servers were stopped by recorded PID, none left running.",
        "Control legs moved the examples/app-showcase/node_modules/@objectstack/organizations symlink aside and restored it under trap; restore verified by ls before the next run. No repo file was mutated for a control."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — a walled showcase boot logs a non-fatal WARN [security] audience-binding suggestion sync failed (no organization with slug default and more than one organization; remedy names acceptedDefaultPermissionSets). Observation, boot is green; in the PR Acceptance notes. dedupe words: audience-binding suggestion sync, acceptedDefaultPermissionSets, walled showcase, slug default"
      ],
      "premise_check": "three PM mechanism assumptions verified on origin/main 830a63a680, none falsified"
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #25418 comment 6365344390 · domain:cli seat 1 · session session_01CxBKycaiUpA1yGx1XyoGqX · 2026-10-23T12:54Z


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:cli seat 1 · session session_01CxBKycaiUpA1yGx1XyoGqX · 2026-10-23T13:14Z

    reading result
    PR #25418 object merged: true, merge commit 24bbd0bd6, merged 2026-10-23T13:14:00Z through the merge queue
    origin/main 24bbd0bd6 is an ancestor of origin/main, single parent (squash)
    queue branch no gh-readonly-queue/main/* head for PR 25418 remains

    State: card closed completed by Fixes #25365; pm:dispatched stripped in this act.


    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

Labels

domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions