Skip to content

feat(services): 18.x step 2 (8b-0e′): sys_secret, the settings audit's global rung and sys_flow_credential go deployment-level, expand-first #24530

Closed

Description

@objectstack-fleet

Filing gate ③: a task the maintainer directed. These are steps 1–3 of the 18.x line, under ruling records 6266750393 and 6267391172 on #15194. The second records the maintainer's 「用量很多,不用节约」: steps 1–3 start now, in parallel.

Part of #15212 (the C8 card), from decisions #24377 Q4 A (ruling 6257510973) and #24435 Q1 A (ruling 6259141885) · Step 2: 8b-0e′, sys_secret, the settings-audit sibling, and the deployment-level sys_flow_credential · ⛔ Not an 18.0 gate.

The line's rule (binding)

Once merged, this PR leaves main releasable:

Expand first. This step only adds: the new write shape, plus reads that accept both the 18.0 shape and the new one. It never moves or deletes an 18.0 row and never drops a column. Each such removal is written down for the step-5 ceremony.

Merge gate. The PR stays a draft until #24522's harness has merged. It lands after it has merged main and is green on R1–R4.

Scope

Three parts. Each can be its own PR, and each must be independently releasable:

Acceptance

  • The new shape is pinned on a fresh install. The dual read is pinned on an 18.0-shaped row.
  • The harness stays green.
  • The report lists every removal the step-5 ceremony owes, table by table.
  • Measure first. If expand-first is impossible or unsafe for any part, stop and report that part with the alternative. Do not build a destructive change.

Activity

  1. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 10 · 2026-10-19T12:42Z
    Session: session_01Y5583bs2RDd53MH6kM1ca3
    Account: os-steve (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-24530-8b0e-deployment-level. If the dev splits this step into several independently releasable PRs, each PR's branch is claude/issue-24530-8b0e-deployment-level-<part> and carries Part of #24530.
    Worktree: the cloud session's own checkout (mode:cloud)
    Domain: domain:services
    Seat: epic:#15194 (the epic lane)
    File surface, read on origin/main at or after 5b14b7f3a. The dev measures first; a breach stops the work and is explained in the report.

  2. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24530,
      "status": "done",
      "branch": "claude/issue-24530-8b0e-deployment-level",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24590",
      "session": "session_01HZT9daB4YX41N1SVVxYcek",
      "premise_still_valid": true,
      "summary": "PR 2a of step 2, per the epic seat's binding scope correction (os-dev-report 6268559156). The new sys_platform_setting_audit is the settings audit trail's global rung: created fresh with systemFields.tenant false and manage_platform_settings, registered in the service-settings manifest, SETTINGS_READ_DOOR_OBJECTS and PLATFORM_OBJECTS_BY_PACKAGE, with an inventory row. buildSettingAuditWriter routes scope global there through one predicate (settingAuditObjectFor), and tenant and user rows stay in sys_setting_audit, stamped. sys_secret and sys_flow_credential are byte-identical to main: their flip was built, measured, then reverted on the seat's correction, and moves to step 6. No 18.0 row is moved, deleted or re-stamped, and no column is dropped. 18.0 global-rung audit rows stay in sys_setting_audit, selected by scope. The census JSON, the tenant-audit census page and counts, and two platform-checklist items are updated with the repo's tooling.",
      "measured": {
        "column_question": "Scratch measurement on this branch, before the revert. Setup: the 18.0 SQLite DDL for sys_secret and sys_flow_credential, populated with 18.0 rows, then ObjectQL.syncSchemas, findV17ShapeTables and detectManagedDrift. (a) systemFields.tenant false with organization_id undeclared: the boot guard flags [sys_flow_credential, sys_secret], so every 18.0 database is REFUSED at boot; the drift offers a destructive drop_column on both (the artifact-pinned boot refuses destructive drift); the additive sync keeps the rows. (b) tenancy.enabled false with organization_id declared: the guard answers [], there is no drift, and the rows are intact. The seat rules (b) a gap, not a route. A third fact was measured on organization-ownership-boot-refusal-order.dogfood.test.ts: moving the two objects' inventory fates to column-drop makes the kept ceremony class block its column-drops step on a column the runtime still declares. Fates restored, and the test is green. Chosen: no change to either object in this step. The sibling is a new table and takes the final shape at once.",
        "eighteen_0_row_behaviour": "Global-rung audit rows an 18.0 install wrote stay in sys_setting_audit, stamped with the Default Organization, and are served by the data API. New global-rung rows go to sys_platform_setting_audit with no organization column. sys_secret and sys_flow_credential behave exactly as on main."
      },
      "ceremony_owes": [
        "sys_setting_audit: move the scope = 'global' rows (18.0 rows are stamped with the Default Organization, so select by scope, never by NULL) to sys_platform_setting_audit. Needs a departures entry on its inventory row, and a MOVES entry in packages/cli/src/utils/organization-ownership-apply.ts like sys_setting's global-rung-move. Then scope's global option can retire, and 8e's NOT NULL applies to the remaining rows.",
        "sys_secret: the flip with step 6, plus column-drops. The declaration goes to systemFields { tenant: false }; the inventory fate goes 3 (attribution) -> column-drop in the same release; the column-drops step drops organization_id; the settings writer stops passing organization_id (settings-service.ts setMany, SettingsSecretStore.insert).",
        "sys_flow_credential: the flip with step 6, plus column-drops. The declaration goes to systemFields { tenant: false }; the inventory fate goes attribution -> column-drop; the column-drops step drops organization_id.",
        "sys_platform_setting_audit: nothing (no column, fate column-drop already recorded).",
        "step 7: remove the dual read. Once the move has run, the global rung's history is sys_platform_setting_audit alone."
      ],
      "tests": "Code head e09294fe1; head 070d81252 adds only regenerated census docs. pnpm --filter @objectstack/service-settings test: 52 files, 892 passed. service-automation test: 192 files, 2546 passed. platform-objects test: 77 files, 1188 passed. cli vitest unit organization-ownership-inventory.test.ts: 25 passed. The cli unit layer in full was 313 files and 4634 passed at e8c32aafb, whose cli diff was identical. lint test: 148 files, 6923 passed (e8c32aafb). Dogfood: settings-audit-global-rung-sibling (new) plus settings-config-change-audit, flow-credential-channel, organization-ownership-boot-refusal-order, settings-organization-isolation and showcase-single-platform-insert-default-organization: 32 passed. Typecheck of spec, platform-objects, service-settings, service-automation and dogfood: exit 0. #24522's harness at branch head f6128e3, run locally on this branch (files restored to the tree only, then removed): 5/5 passed (R2 boot plus data, R3 v17 refused). Fresh showcase boot (pnpm dev -- --fresh -p 38517): discovery 200; PUT /api/settings/ai and /branding 200; /data/sys_platform_setting_audit holds the auth and ai global rows with no organization; /data/sys_setting_audit holds only tenant rows, stamped. R4: OS_TENANCY_POSTURE=isolated pnpm dev -- --fresh exits 1 with 'tenancy posture isolated is not supported in 18.0 (NOT_IMPLEMENTED)'. Ablation X6, via scripts/ablation-replace.mjs: settingAuditObjectFor rewritten to route global to sys_setting_audit, service-settings rebuilt, ablation-dist-preflight showed the marker present in 2 dist files. Red: the expand pin 2 of 4, the routing pin 2 of 6, the dogfood pin 2 of 4. Restored to the HEAD blob, rebuilt, and preflight --absent passed. The first X6 attempt was a no-op: tsc refused the marker spelling (TS6133), so no pin ran. Earlier ablations X1-X5 were on the reverted sys_secret and sys_flow_credential pins and no longer apply.",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 126 commands at e09294fe1 (21 paths, 915 changed lines). They were run with exit codes written to a file before any pipe, plus 12 more: the 9 roster families marked with the roster-under-your-path sign, check:tenant-chokepoint, check:object-def-param-keys, check:durability-log-level, check:startup-registry-verdict and check-nul-bytes. 136 of 138 exited 0. The two reds were check-tenant-audit-census and its --self-test: the census drifted after the revert. Fixed by tenant-audit-census.mjs --write in 070d81252, then both re-run: exit 0. The 29 doc and census families were re-run on 070d81252: all exit 0. check-plugin-teardown-shape --self-test needed git fetch of 621a4876 (shallow clone), then exit 0. check:dual-build-cjs-loads needed the 8 unbuilt packages built, then exit 0. CI check-runs on PR #24590: not yet reported (in_progress), and not waited on. NOT MEASURED locally, owned by CI: Test Core shards, Build Core, the workspace type-check lanes, and dogfood (main-only battery).",
      "mcp_calls": "0",
      "api_writes": "2: (1) the fleet-write relay pr_create, run 39275218201 = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/24590/assignees [os-steve], read back byte-identical; (2) this os-dev-report comment, POST /repos/objectstack-ai/objectstack/issues/24530/comments via the same relay",
      "open_questions": [
        {
          "question": "Scope correction: the epic seat's binding message (step 0's measured plan, os-dev-report 6268559156, F2 and step_plan flag 1) took the sys_secret and sys_flow_credential flip out of this step, after I had built it as tenancy.enabled false with the column declared. Was that taken correctly?",
          "options": [
            "A: reverted to main and recorded in ceremony_owes as the step-6 flip plus column-drops (taken)",
            "B: keep the expand spelling"
          ],
          "recommendation": "A. The seat rules the tenancy.enabled spelling a guard gap, and the kept ceremony class blocks column-drops on a column the runtime still declares (measured)."
        },
        {
          "question": "The seat's correction asks that the settings history readers union the sibling with sys_setting_audit WHERE scope = 'global'. No in-process history reader exists: the only readers are the two generic data-API grids behind SETTINGS_READ_DOOR_OBJECTS. Should a reader be built?",
          "options": [
            "A: no new surface; both grids serve their rows, and the dogfood pin reads both by scope (taken)",
            "B: add a settings history API that unions the two"
          ],
          "recommendation": "A. A union API would be new public surface that nothing reads today. If a Setup history view needs one, it is its own card."
        },
        {
          "question": "The sibling's name and shape.",
          "options": [
            "A: sys_platform_setting_audit, the same row shape as sys_setting_audit, scope restricted to the single option global (taken)",
            "B: drop the scope column"
          ],
          "recommendation": "A. It mirrors sys_platform_setting, and one reader reads both tables with the same columns."
        },
        {
          "question": "One PR, or the up-to-3 split?",
          "options": [
            "A: one PR, Closes #24530 (taken)",
            "B: a split"
          ],
          "recommendation": "A. After the scope correction only one part remains."
        },
        {
          "question": "Changeset disposition.",
          "options": [
            "A: Clause-②: yes (narrowing), minor, ADR-0087 not-required (no-migration-prescription), before/now/remedy (taken)"
          ],
          "recommendation": "A. The new object widens the surface. Who can read new global-rung audit rows narrows. No metadata key is retired: sys_setting_audit.scope keeps its global option because 18.0 rows hold it."
        }
      ],
      "out_of_scope_findings": [
        "carrier: epic seat (session_01Y5583bs2RDd53MH6kM1ca3) — ADR-0131 D7's dated notes for Q4 A (sys_setting_audit) say 'has not shipped'; after this lands that half is shipped (docs/adr is Tier H, outside this claim). Noted, not filed.",
        "carrier: epic seat — docs/qa/platform-checklist/areas/platform-core.json items settings-hub-roundtrip (rev 5) and settings-audit-secret-fingerprint (rev 3) were re-pointed in this PR because their clauses read the global rung's audit rows from sys_setting_audit; outside the claim's named surface, recorded in the PR body."
      ],
      "deviations": "Edited docs/qa/platform-checklist (two items) and content/docs/permissions/tenant-audit-census.mdx plus docs/audits/2026-08-tenant-audit-write-call-sites.counts.md (generator-regenerated, with the gate-held prose figures). Neither path is in the claim's named surface. Both followed from the change. The commit history keeps the reverted flip, plus a revert commit naming the seat's correction. Worked in a linked worktree (../objectstack-issue-24530); the primary checkout was left detached at 5b14b7f."
    }

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report addendum

    PR #24590 (session session_01HZT9daB4YX41N1SVVxYcek), the merge gate the seat asked for:

    • Merge: origin/main merged at 5d8d4addc5. It is a clean merge, and it brings the harness (ec16dbe2e) onto the branch.
    • Follow-up commit 237db494eb (current head). Two parts:
      • the tenant-audit census, regenerated on the merged tree with tenant-audit-census.mjs --write (one row in each of its two files);
      • the two review cosmetics: the settings-service.ts read-door docblock now names four stores, and the config-change-audit.test.ts dual-write title names the sibling.
    • Harness, on the merged tree: run under os-verify-lock after building the dogfood closure. pnpm --filter @objectstack/dogfood exec vitest run test/upgrade-18x-harness.dogfood.test.ts test/settings-audit-global-rung-sibling.dogfood.test.ts: 2 files, 9 tests passed (the harness 5/5, the sibling pin 4/4).
    • Other local runs on the merged tree:
      • pnpm --filter @objectstack/service-settings test: 52 files, 892 passed.
      • check-tenant-audit-census: OK.
    • CI on 237db494eb: every check-run is queued; none has concluded yet. Not waited on.

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report addendum

    PR #24590 (session session_01HZT9daB4YX41N1SVVxYcek), rebased onto the step-3 landing (fbafb85) by merge, as the seat asked. No rebase and no force-push.

    • Merge: origin/main at c3954057f merged as 030483e7f5.
      • The tenant-audit census page and counts conflicted. I took main's text, then regenerated both with tenant-audit-census.mjs --write.
      • The census JSON was deferred by the os-regen driver and regenerated with pnpm gen:platform-object-tenancy-census.
      • The inventory, platform-object-names.ts and the checklist JSON merged cleanly, with both siblings kept: sys_identity_email and sys_platform_setting_audit.
      • Neither checklist item this PR bumps was bumped on main. Their histories are main's, plus this PR's entries on top (revisions 5 and 3).
    • New head: 2b295cabd4. It is the regeneration commit, and it discharges the os-regen deferral. The page's gate-held figures carry this PR's +1 write site: 232 sites, 158 decidable.
    • Harness and pins (under os-verify-lock, after building the dogfood and cli closures). One dogfood run covered the harness (upgrade-18x-harness, 5/5), settings-audit-global-rung-sibling, settings-config-change-audit and organization-ownership-boot-refusal-order: 4 files, 18/18 passed.
    • Package suites:
      • service-settings: 52 files, 892 passed. This includes the expand pin, the routing pin, the read-door pin and the manifest pin.
      • platform-objects: 78 files, 1192 passed. This includes the D7 family pin.
      • cli organization-ownership-inventory.test.ts: 25 passed.
    • Gates (exit 0):
      • check-tenant-audit-census and its --self-test;
      • check-platform-object-tenancy-census;
      • check-platform-checklist;
      • check:i18n and check:i18n-coverage;
      • check-nul-bytes;
      • check-adr-0087-registration and check-changeset-no-major (both --base origin/main).
    • Untouched: the PR's ready state and auto-merge.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed and closed · epic PM session_01Y5583bs2RDd53MH6kM1ca3 (os-steve) · 2026-10-19T19:09Z. PR #24590 (18.x step 2, 8b-0e′: the settings audit trail's global rung moves to a deployment-level sibling, sys_platform_setting_audit) has merged.

    reading value
    PR #24590 merged: true; merge commit b12e16a56
    contract review 6271127207, CONTRACT_REVIEW_TIER, PASS
    R2 harness 5/5 on the merged tree (addenda 6271413038 and 6273069431; the second covers the main merge after #24587, with both siblings in the regenerated census)

    Delivered (a complete feature, per 6270035914).

    • A new global-rung audit row goes to sys_platform_setting_audit, with no organization column. Reading it needs manage_platform_settings.
    • Tenant and user rows stay in sys_setting_audit, stamped as before.
    • 18.0 global rows stay where they are and readable. Select them by scope = 'global', never by NULL.

    Carried to the steps 5+6 landing (#24581 / #24582).

    The card closes completed. The dev session is archived.

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