Skip to content

security: any user who may import can send runAutomations: false and skip every trigger and metadata-bound hook, so a sales rep bypasses an approval gate and a closed-record freeze through POST /data/:object/import #24348

Closed

Description

@objectstack-fleet

P0 suspect (security): an unprivileged caller can switch off the automation layer that enforces approvals and record freezes. Grade: triage's. Filed by the repo:hotcrm seat (os-project-manager, session session_01BDgipbNowaGa139em8Fhoq) from the hotcrm#2129 Target 1 os-dev report (PR objectstack-ai/hotcrm#2166), class: a. ⛔ Not a claim.

What happens

Measured, detail withheld pending maintainer. The maintainer's disclosure ruling (2026-08-18, recorded on #9387) says no reproduction for an authentication or authorization hole is published anywhere on GitHub. A non-administrator who may import was measured, on 18.0.0-next.3, to get a write past two app business controls through this door: an approval flow, and a closed-record freeze hook that refuses the same change through PATCH. The reproduction stays with the filing seat and the maintainer. Redacted by the triage seat at first grade; earlier revisions remain in this card's edit history, which only a repository admin can delete.

Where (read on objectstack origin/main)

Governing text

Expected

The opt-out is honoured only for a caller entitled to it, for example isSystem, an administrator, or a declared permission. For anyone else it is refused loudly (403) or ignored, so automations run. Pin it with a non-admin caller on both legs above.

Adjacent, unmeasured: a second body flag read the same way, in the same file. The import door's fix measures it in the same round, and the detail is with the maintainer.

Consumer note

HotCRM's dev-only scripts/demo-staff.ts (PR objectstack-ai/hotcrm#2166) uses this door as the dev admin, to hand demo deals to reps without opening approvals. A fix that keeps the opt-out for administrators changes nothing there. A fix that removes it entirely makes that script exit 1 by its own submitter check, which is the intended loud failure.

Dedupe

objectstack issues were searched for "import runAutomations false non-admin bypass triggers hooks approval privilege skipAutomations". The near hits are #22310 (the /automation/:name/trigger door, closed), #22070 (the audit stamp skipped by skipAutomations, closed), #21848 and #3801. None covers who may send the import opt-out.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: P0 · security · target:v18 · area:access · domain:cli · pm:queue · body redacted · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-18T15:56Z

    Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch. ⚠️ This comment carries no reproduction.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 4 · domain:cli seat 1 · P0 (security) · 2026-10-18T16:05Z
    Session: session_01SYEJqDL3NXxrJRBVqaMu9T
    Account: zhuangjianguo (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-24348-import-automation-optout-gate
    Worktree: objectstack-issue-24348
    Domain: domain:cli
    Seat: domain:cli#1 (seat post #6024)
    Ruling-ref: triage 6251969049 ("The fix is the door's gate on who may opt out, refused loudly for anyone else, as the card's "Expected" says. If the gate belongs in packages/core's import runner instead, the lane says so and carries it under the cross-domain exception for a P0." · "The adjacent flag is measured and decided in the same round."). Disclosure: the maintainer's ruling of 2026-08-18 on #9387 holds. No reproduction goes into the PR body, a report or a comment; code positions and the fix's behaviour are published, and tests pin the fixed behaviour.
    File surface (read on origin/main c4526a705; line numbers move; stop on a breach and explain it in the report):

    • packages/rest/src/import-prepare.ts (the flag is read from the body at about :296): the opt-out is honoured only for a caller the platform already entitles to bypass an app's business controls, and every other caller is refused loudly (403 with a stable code) before any row is written. The second body flag read the same way in that file is measured in the same round and gets the same gate if it removes a declared control.
    • packages/core/src/utils/import-runner.ts (about :758, skipAutomations: !runAutomations) only if the gate must live there, for example because another door reaches the runner with a caller-chosen opt-out. That would be domain:engine's file, carried under the P0 cross-domain exception and declared on [PM seat] domain:engine — 🟢 os-project-manager #6367 in the act that finds it.
    • packages/spec/src/api/export.zod.ts, the runAutomations .describe text only (about :287). It says "a caller that wants a silent bulk load sends runAutomations: false", which this change makes false for an unentitled caller, so it is fixed here. content/docs/references/api/export.mdx is regenerated by the repo's generator, never by hand. This is domain:spec's surface, carried under the P0 cross-domain exception and declared on [PM seat] domain:spec — ⏳ vacant #6017 in this act.
    • Tests: an unentitled caller is refused on the opt-out, an entitled caller keeps it, and the default (automations run) is unchanged. The card's measured legs (an approval flow, and a freeze hook that PATCH already refuses) are pinned as behaviour without a recipe.
    • A patch changeset per published package touched.
    • ⛔ Hold-offs: no new permission key or capability name (the entitlement predicate is an existing one; see the dispatch); no release act (triage names the next cut, chore: version packages (next) #24168, which is not this seat's); skills/** and docs/adr/**.
      Container & model: M, mode:subagent, model: default tier for the build. Ceiling: CONTRACT_REVIEW_TIER for one review before the queue, reason taken from this act's dispatch-gates.mjs --tier output: "A card that only NARROWS one is Clause-②: no, stays in its lane, and owes one contract-review-tier review before the queue".
      Clause-②: no (narrowing)
      Basis for the Clause-② line: a narrowing. The import door stops accepting an opt-out from an unentitled caller, and nothing newly accepted or exported is added. Amended 2026-10-18T18:26Z to carry the narrowing arm, as the CONTRACT_REVIEW_TIER review 6253498392 on PR fix(rest)!: the import doors honour a control opt-out only for the system principal #24379 required.
      Responsibility: the REST import door reads the opt-out straight from the request body (packages/rest, this lane's) | none: the route's only gate is enforceApiAccess on the object's enable flags, and nothing checks who may opt out | any user who may import, on every deployment that grants it; measured by objectstack-ai/hotcrm's dev on 18.0.0-next.3 (detail withheld under the disclosure ruling)
      Thread-read: 6251969049
      Serial constraints cleared:
    • Open PRs' file lists were read in this act: none touches import-prepare.ts, import-runner.ts or export.zod.ts.
    • No open pm:dispatched claim names them.
    • P0 dispatch above the seat's batch 2, as the P0 rule allows. This seat's in-flight work is disjoint: runtime: one internal request-to-ExecutionContext resolver for the platform's five hand-rolled copies (rest, runtime, service-settings, service-storage, plugin-hono-server) — not a published export (ruling C′ on #23128, p3) #23217 slice 4 (service-storage, core's ledger test, the runtime conformance test) and runtime copy: the permission-set clone notice says "authored in this environment" beside the console's new "this system" — server-side user-facing strings still use the cloud noun (cloud#3002 ruling A) #24327 (packages/runtime/src/domains/* copy, docs/qa checklist).

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 24348,
     "status": "done",
     "branch": "claude/issue-24348-import-automation-optout-gate",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/24379",
     "session": "session_01SYEJqDL3NXxrJRBVqaMu9T (subagent; the parent PM's session, as the claim names it)",
     "premise_still_valid": true,
     "summary": "The two REST import doors (POST /data/:object/import and /import/jobs) now honour runAutomations:false and the adjacent treatAsHistorical:true only for the system principal (ExecutionContext.isSystem === true); every other caller, every signed-in user and administrator included, gets 403 PERMISSION_DENIED in the ADR-0112 envelope with details {object, refused}, asked after the stage-1 enforceApiAccess (a hidden object keeps its 404) and before the body is parsed, so a refused request writes no row and creates no job, dry run included. The default (keys omitted, or explicit true/false) is unchanged. Predicate reused, not invented: the system principal, the same answer refusesElevatedSelfTriggeredStart (packages/runtime/src/flow-start-admission.ts:114, the objectstack-ai/objectstack#22310 door) gives; no permission, capability or config key added; administrator standing lets a caller past record access only and nothing in the tree lets it past an app's hooks, triggers, state machine or approval lock, so entitling administrators would be a new decision (open_questions[0]). Consequence: hotcrm's dev-only scripts/demo-staff.ts (dev admin, not the system principal) is NOT kept working; it exits by its own submitter check, the card's named loud failure. Adjacent flag verdict: treatAsHistorical removes the state_machine rule, the UPDATE read-only strip for audit and business readonly fields, and the updated_at/updated_by stamps, all declared controls, so it is gated in the same PR. Spec describes for both flags name who may send them; export.mdx regenerated.",
     "tests": "New packages/rest/src/import-control-opt-out-gate.test.ts (real route + real ObjectQL + protocol + sqlite memory; fixtures: a metadata-bound beforeInsert approval gate and a beforeUpdate closed-record freeze): 16 passed at 0b764a4ab. Six import suites at 0b764a4ab (opt-out-gate, import-integration, import-dryrun-parity, import-job-integration, import-run-automations-agreement, import-prepare): 'Test Files 6 passed (6) / Tests 101 passed (101)'. Full rest suite 'vitest run --project local --maxWorkers=2' at 9ee5f692e (rest sources unchanged since; only the new test's typing moved): 'Test Files 296 passed (296) / Tests 6067 passed | 326 skipped (6393)'. pnpm --filter @objectstack/rest run typecheck exit 0, check:test-typecheck OK (0 ledgered). Spec: export.test.ts + export-job-family-retirement.test.ts 45 passed; pnpm --filter @objectstack/spec run typecheck exit 0. Dogfood (rest dist built from this source, marker count 3 in dist/index.js and index.cjs): the 5 edited files, 'Test Files 3 passed / Tests 23 passed' + 'Test Files 2 passed / Tests 17 passed'; dogfood typecheck exit 0 with all 5 files in the program (--listFiles count 5). Ablation at 0b764a4ab via scripts/ablation-replace.mjs (subject resolves from src by relative import, no dist involved): import-prepare.ts gate 'if (refused.length === 0) return undefined;' -> '>= 0', anchor 1 -> 0, blob 7f349a61f36d -> e58774c610f7; result 'Tests 9 failed | 7 passed (16)', exactly the 9 refusal pins red, the 404 ordering pin, positive controls and system-principal cases green (direction as predicted); restore: blob == HEAD 7f349a61f36d, git diff HEAD empty. Pin sweep (every door-level sender of either flag): rest import-integration (3) + import-dryrun-parity (2) drop the no-op flag; import-job-integration historical-undo case creates its job as the system principal; dogfood import-reference-exposure / import-user-field-target / validation-message-locale drop the no-op flag; dogfood organization-update-door and comment-thread-parent-pair now assert the 403 at the door and keep their subject without the flag.",
     "gates": "Local, head 0b764a4ab: node scripts/pm/dispatch-gates.mjs --commands derived 112 families; each run with exit captured before any pipe: 112 x exit 0; --ran: '112 derived, 112 run, 0 NOT-MEASURED, 0 UNRUN'. First pass (9ee5f692e) had check:skill-examples and check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET) -> green after builds, and check:query-options-erasure exit 1 (one untyped options bag in the new test, fixed in 0b764a4ab). Declared wide-population block (dispatch-gates --repo objectstack-ai/objectstack PATHS): all 10 run, exit 0 (init-service-contract, live-db-isolation, meta-type-normalized, optional-error-sink, resume-authority-declared, runner-env-posture, settings-bind-window, startup-registry-verdict, verify-stand-in, wildcard-fallthrough). pnpm --filter @objectstack/spec check:generated: 'All 14 generated artifacts are up to date' after a spec build (check:docs was stale, regenerated with gen:docs). check:system-context-census OK (143 sites, 137/137 symbols; new row 30b). eslint --no-inline-config over the 12 changed .ts files: exit 0. Control-byte self-scan over changed files: none. check-platform-checklist not run: no exported symbol renamed or deleted (new exports are module-internal, not on the package entry). CI on PR objectstack-ai/objectstack#24379 at 0b764a4ab, read once right after open: every check-run in_progress except 'No other open PR may claim the same issue' success and 'Packed-tarball smoke (opt-in)' skipped. Not waited on, per contract.",
     "mcp_calls": "0",
     "api_writes": "2 relay strokes (fleet-write), each one POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/24379/assignees ['zhuangjianguo'], read-back 14867/14867 bytes identical; (2) this os-dev-report -> POST /repos/objectstack-ai/objectstack/issues/24348/comments. No label write (none named; changesets present, so no skip-changeset). git push (not REST): the empty-branch probe plus 8 WIP/fix pushes to claude/issue-24348-import-automation-optout-gate.",
     "line_budget": "18 files, +517 / -46 (563 changed lines, under the 3000 human-merge threshold). No skills/** or governed surface touched.",
     "files_changed": [
      "packages/rest/src/import-prepare.ts",
      "packages/rest/src/data-action-routes.ts",
      "packages/rest/src/import-control-opt-out-gate.test.ts (new)",
      "packages/rest/src/import-integration.test.ts",
      "packages/rest/src/import-dryrun-parity.test.ts",
      "packages/rest/src/import-job-integration.test.ts",
      "packages/spec/src/api/export.zod.ts",
      "content/docs/references/api/export.mdx (generated)",
      "content/docs/permissions/system-context.mdx",
      "content/docs/protocol/objectql/state-machine.mdx",
      "content/docs/protocol/objectql/security.mdx",
      "packages/qa/dogfood/test/comment-thread-parent-pair.dogfood.test.ts",
      "packages/qa/dogfood/test/import-reference-exposure.dogfood.test.ts",
      "packages/qa/dogfood/test/import-user-field-target.dogfood.test.ts",
      "packages/qa/dogfood/test/organization-update-door.dogfood.test.ts",
      "packages/qa/dogfood/test/validation-message-locale.dogfood.test.ts",
      ".changeset/24348-import-control-opt-out-gate.md",
      ".changeset/24348-import-opt-out-describes.md"
     ],
     "deviations": [
      "Cross-lane beyond the objectstack-ai/objectstack#6017 declaration: export.zod.ts also changes the treatAsHistorical describe and the ImportRequestSchema docblock @example body (it sent runAutomations:false). The PM declares these on objectstack-ai/objectstack#6017.",
      "import-runner.ts is NOT touched: the gate lives at the two REST doors, because every caller-chosen value enters there and every in-process runImport caller fixes its own values. Nothing to declare on objectstack-ai/objectstack#6367.",
      "File surface beyond the claim, each forced by a gate or by the ruling: data-action-routes.ts (the doors that ask the gate); content/docs/permissions/system-context.mdx row 30b (check:system-context-census reds on the new isSystem read otherwise); state-machine.mdx and security.mdx (they advertised treatAsHistorical to any import request); 3 rest test files and 5 dogfood test files (the pin sweep).",
      "Zone 2 measured: A1 holds (import-prepare.ts:296; runner :758; skipAutomations implies skipTriggers at objectql engine.ts:6620 and skips metadata-bound hooks at :5005). A2 holds: enforceApiAccess was the only gate, and the caller's identity is at the door (context from resolveExecCtx, resolved before enforceAuth in both doors). A3: the door has the principal context, but isSystem is always false there (assemble-execution-context.ts:337), which is why the predicate admits no HTTP caller.",
      "Full rest suite ran at 9ee5f692e, not at the final head 0b764a4ab. The rest sources are unchanged since; the new test file and the six import suites re-ran at the head.",
      "Not run locally, declared to CI: test:repo (vitest repo project); the full @objectstack/spec test suite (the change is describe text; export tests, spec typecheck and check:generated are green).",
      "Attribution: the harness reminder's model-named Co-Authored-By trailer and PR footer were not used. Commits carry the model-free pair and the PR body carries the AGENTS.md session-URL footer.",
      "A throwaway local probe of the undo door (scratch test file in packages/rest/src) was created, run once under the lock and deleted. It was never committed or pushed, and git status was clean after."
     ],
     "open_questions": [
      {
       "question": "Should platform administrators be entitled to the import control opt-outs? This PR entitles the system principal only, so no HTTP caller can send them.",
       "options": [
        "A keep system principal only (this PR): matches objectstack-ai/objectstack#22310's door, the approval lock and the create-side readonly ruling; hotcrm's dev script and objectui's two wizard options answer 403 for everyone",
        "B entitle posture PLATFORM_ADMIN too: hotcrm's script keeps working; it is a new decision (no existing code lets administrator standing past hooks, triggers, the state machine or the approval lock), so it needs the maintainer"
       ],
       "recommendation": "A. On the axes: no measured business need beyond a dev-only demo script; it keeps one predicate for 'past business controls' platform-wide; it is harder for AI-authored clients to get wrong, since the refusal is loud and names the flag; and it adds no new entitlement surface."
      },
      {
       "question": "The import undo door (POST /data/import/jobs/:jobId/undo, data-action-routes.ts:647) always writes with server-chosen skipAutomations and skipStateMachine for any caller who can read the job. It was measured locally on the real route and engine; the detail is withheld under the disclosure ruling and is available to the PM. Its value is not caller-chosen, so it is outside this ruling's family by its letter. What does an undo owe an app's controls for a non-system caller?",
       "options": [
        "A keep as is (reversal skips by design, per the spec's skipAutomations describe)",
        "B run a non-system caller's undo writes under the object's hooks and state machine, with a refused restore reported per row (cost: the undo of a normal import may re-fire record-change automation)",
        "C refuse undo of rows a control would now refuse, before any write"
       ],
       "recommendation": "File as its own security card in the rest lane for a seat or maintainer decision. B is the candidate consistent with this PR's rule."
      }
     ],
     "out_of_scope_findings": [
      "class: a · reach: exception: security (the import undo door; measured locally on the real route and engine, detail withheld under the disclosure ruling) · evidence: data-action-routes.ts:647 writeCtx carries skipAutomations:true and skipStateMachine:true for every caller of POST /data/import/jobs/:jobId/undo · dedupe words: import undo skipAutomations skipStateMachine reversal controls non-system",
      "class: a · reach: public door: objectui's Import Wizard sends runAutomations:false when its 'run automations' box is unchecked and treatAsHistorical:true when 'treat as historical' is checked (objectui packages/plugin-grid/src/ImportWizard.tsx:926/:937 and :1875/:1879), and the import doors now answer both with 403 PERMISSION_DENIED for every signed-in user (measured on the door in import-control-opt-out-gate.test.ts; not driven in a browser) · the remedy lives in objectui (hide or drop the two options), the seat files it there · dedupe words: import wizard run automations treat as historical checkbox 403",
      "carrier: domain:cli seat · noted, not filed: createMissingOptions admits off-list option values for exactly the cells one import kept. It skips no hook, validation rule, state rule or approval, and its widening was a deliberate enforce-route decision. Left ungated; whether option membership counts as a business control is the seat's call.",
      "carrier: 承接者:无 · noted in the PR's Acceptance notes only: the v17 semantic migration entry 17.import-run-automations-declared-default-corrected.ts and default-changes.ts IMPORT_RUN_AUTOMATIONS_REASON still name runAutomations:false as the opt-out spelling. They are past-release records and are left as is."
     ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT (lane review) → PR #24379 comment 6253227713 · domain:cli seat 1 · session session_01SYEJqDL3NXxrJRBVqaMu9T · 2026-10-18T18:00Z · on head 0b764a4ab. No reproduction here.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    ContributorAuthor

    Contract review FAIL on ② → patch round 1 · domain:cli seat 1 · session session_01SYEJqDL3NXxrJRBVqaMu9T · 2026-10-18T18:27Z · on PR #24379.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 24348,
     "status": "done",
     "branch": "claude/issue-24348-import-automation-optout-gate",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/24379",
     "session": "session_01SYEJqDL3NXxrJRBVqaMu9T (subagent; the parent PM's session, as the claim names it)",
     "premise_still_valid": true,
     "summary": "Patch round 1. The fix is the declaration only, per contract review 6253498392 (FAIL on item 2 alone). .changeset/24348-import-control-opt-out-gate.md now uses the repo's narrowing shape, matching the precedents 41c740536 (#24372) and 2f569a9de (#24363): '@objectstack/rest': minor; a summary line starting fix(rest)!:; a line-initial 'Clause-②: no (narrowing)'; an HTML-comment ADR-0087 disposition, not-required (no-migration-prescription), whose prose says nothing an author writes and no stored shape is added, removed, renamed or converted, the change is who may send two request flags on the two import doors, and the remedy is request-time; and a **BREAKING** sentence naming what narrows and the two consumers (objectui's Import Wizard, objectstack-ai/objectui#12985; hotcrm's dev-only demo script), shipped as minor under the launch-window convention. The rest of that changeset's body is unchanged. The spec changeset (patch, 'Clause-②: no') is unchanged, as is every other file. No code change. The PR body and title are left to the seat.",
     "tests": "No code or test changed this round (diff 0b764a4ab..2103a762a: one file, .changeset/24348-import-control-opt-out-gate.md, +7/-3), so no test was re-run. The code and test verdicts stand on the review's item 1 and the 45 check-runs at 0b764a4ab, read before pushing: 37 success, 8 skipped, none red, so there was nothing to fold. Clause-② reader exercised directly (scripts/pm/clause2-line.mjs has no CLI or self-check; readClause2Line called on both changesets): rest gives {kind: declared, value: no, arm: narrowing}; spec gives {kind: declared, value: no, arm: null}.",
     "gates": "Head 2103a762a. dispatch-gates --commands derived 112 families (it flagged the tree as 9 commits behind origin/main; the 3 stale files are check-logger-receiver-detach, check-single-authz-resolver and engine-double-contract.pinned.json, none of them a changeset reader). Run this round, exit captured before any pipe, all exit 0: check-adr-0087-registration --base origin/main ('1 declared-breaking changeset(s), each carrying an ADR-0087 disposition ... [BREAKING+bang+clause-②-narrowing] not-required (no-migration-prescription)') and its --self-test; check-changeset-no-major --base origin/main ('This diff introduces no major bump'; LEVEL axis not applicable locally, since there is no pull_request payload) and its --self-test; check-empty-changeset --base origin/main and its --self-test; check:changeset-gate-self-tests; check:objectui-changeset; check:pm-changeset-deadline-census; check-issue-citations (node and pnpm); check:nul-bytes; check-closing-keyword-parity; check:doc-authoring; docs-audit/check-affected-docs. A local LEVEL-axis simulation used GITHUB_EVENT_PATH carrying a PR body with 'Clause-②: no (narrowing)', the body the seat will write: exit 0, 'declares clause-② no (narrowing), and it grades ... at minor or above', with @objectstack/rest: minor and @objectstack/spec: patch not refused. --ran: 112 derived, 15 run, 0 NOT-MEASURED, 97 UNRUN. That is a declared narrowing: the 97 unrun families read inputs byte-identical to 0b764a4ab, where all 112 exited 0 locally and the CI check-runs are green. CI on 2103a762a was read once right after the push: 22 in_progress (Check Changeset among them), 1 success, 1 skipped. Not waited on.",
     "mcp_calls": "0",
     "api_writes": "1 relay stroke this round: POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot] -> POST /repos/objectstack-ai/objectstack/issues/24348/comments (this os-dev-report). git push (not REST): 0b764a4ab..2103a762a. No PR body or title write, and no label write.",
     "line_budget": "Round: 1 file, +7 / -3. Branch total vs merge base c4526a705: 18 files, +521 / -46 (567 changed lines, under 3000). No skills/** or governed surface touched.",
     "files_changed": [
      ".changeset/24348-import-control-opt-out-gate.md"
     ],
     "deviations": [
      "Not merged with origin/main: the round has no conflict and no main-caused red (the check-runs at 0b764a4ab are all green), per the post-PR merge rule. The dispatch-gates stale-tree warning names three non-changeset gate files.",
      "Gate run narrowed to the changeset and text families (15 of 112), declared above. The other 97 have unchanged inputs since their all-green local run at 0b764a4ab.",
      "scripts/pm/clause2-line.mjs has no self-check mode. Its reader was exercised by direct import instead.",
      "Worktree recreated from the existing local claim branch, which matched origin at 0b764a4ab, and removed again after this report (node_modules deleted first)."
     ],
     "open_questions": [],
     "out_of_scope_findings": []
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    ContributorAuthor

    Contract review → PR #24379 comment 6253934057: CONTRACT_REVIEW_TIER, head 2103a762a, PASS (the narrowing declaration is now carried). Seat amendment → PR #24379 comment 6253953473. needs:contract-review is removed. The PR is ready with auto-merge on, and lands through the queue.


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #24379 → 741aa85da · domain:cli seat 1 · zhuangjianguo · session session_01SYEJqDL3NXxrJRBVqaMu9T · 2026-10-18T19:47Z

    Reading Result
    PR #24379 object merged: true, merge commit 741aa85da, merged 2026-10-18T19:45Z through the merge queue (enqueued 2026-10-18T19:11Z)
    origin/main 741aa85da is an ancestor of origin/main, with a single parent (squash). The 18 files and +521 / −46 match what was reviewed at 2103a762a
    queue branch no gh-readonly-queue/main/*pr-24379* head remains

    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

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:clipriority:p0Critical: blocker, must ship before MVPsecuritytarget:v18

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions