Skip to content

fix(store): make assignment planning authorization atomic (M4B-3) - #1852

Merged
mergify[bot] merged 2 commits into
mainfrom
codex/m4b-3-assign
Oct 22, 2026
Merged

mergify[bot] merged 2 commits into
mainfrom
codex/m4b-3-assign

Conversation

@Cuarroc

@Cuarroc Cuarroc commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Zuweisungen prüfen ihre Berechtigung jetzt atomar beim Schreiben.
Damit kann ein überholter Koordinator keine Zuweisung mehr nach einer bereits bestandenen Vorprüfung speichern.
Für dich ist nichts zu tun; unabhängige Prüfung und Abnahme stehen noch aus.

Report

Plan-ID: Z4-M4B-3-ASSIGN

Tier: A. Operator: UMSETZEN. Owner: srv-m4b-3-assign. Parent: Z4 / M4B, Root acceptance. Ticket: 15d92066-a3aa-4fb0-a91c-bdaf5434550d.

Candidate: e341b6f5999ded2304ace30248fcf2bde032df0d on codex/m4b-3-assign. Pinned base / merge-base: 8c86bfc44c50e55209da7de48fdc7e3cb692a750. Raw size: 242 additions plus deletions across 9 files, including tests, compatibility declarations and PLAN; no exclusions. Limit: 300.

What changed

  • The required assignment backend method explicitly forwards Option<PlanningAuthority> to the real Store writer. The obsolete API legacy method is removed; the legacy Store wrapper is test-only. IMPORT remains its existing pass-through. Production GOAL/TASK writers are unchanged.
  • assign_continuous_task_with_authority obtains BEGIN IMMEDIATE through the existing continuous::begin_write helper. It then checks run, owner, live fence, dispatch role and target task project through require_planning_authority on that same transaction. Assignment admission, revision checks, upsert and team_assignment event use that transaction and commit together. There is no second authorization transaction.
  • A scoped coordinator cannot assign the normalized coordinator role, including padded input. Refusal uses the existing PLANNING_REFUSED vocabulary and HTTP 403/refused audit mapping. Explicit operator None retains the frozen policy and may assign coordinator work.
  • Existing expected-revision conflicts, retry after claim, frozen policy, goal/deadline and claim checks remain. The separate HTTP planning audit envelope is still appended after the writer transaction; this package does not make that audit append atomic.
  • PLAN changes are restricted to TASK and ASSIGN status cells: TASK records actual fix(store): make task planning authorization atomic (M4B-2) #1849 merge at 2026-10-22T21:03:34Z and its SHA; ASSIGN states its post-merge boundary. IMPORT and existing GOAL residuals remain open, including ticket 2dbc396c-9b74-4556-9c28-d9e00f5c6310. Tickets 0ce06131/d2d1a8a8 and G5/D4 are not closed. Continuous remains disabled/frozen.

Public semantic proof

The new HTTP test api::tests::planning_access_tests::planning_assignment_fence_interleaving_rejects_without_assignment_or_event uses real SQLite and a real scoped coordinator credential. Its coordinator task is distinct from the open, unclaimed target. A bounded fixture handshake proves HTTP role/project prechecks have completed, then an independent connection advances the live coordinator fence before writer admission. Sender drop precedes scoped joins on unwind; no sleeps or production hooks are used.

The compiling RED commit 9a11625612909d5272109753e2c05247d4b102df changes only tests; its native fixture calls the existing legacy Store assignment writer against frozen production. The assertion fails with exit 101: HTTP 200, assignment revision 1 and an accepted audit envelope, instead of 403/refused. There were no compiler errors. On the candidate, the same test function is byte-identical; only fixture writer delegation changes. It passes and verifies the full public assignment (including revision) and public continuous_changes events are unchanged, plus the refused audit envelope.

Separately, post-fix native controls cover successful own-project HTTP assignment; direct public Store refusal of missing run, wrong owner, stale fence, missing/foreign target, wrong role and padded coordinator escalation; no partial assignment/revision/events in either project; operator HTTP coordinator assignment with explicit taskId/role/revision assertions. This sibling test is post-fix guard coverage, not the compiling semantic RED proof.

The stock exact selector on the pinned base exited 0 with zero tests. That is absent-selector evidence only, not semantic RED. --list after adding the fixture found the exact test; candidate listing finds both new selectors.

Evidence

Commands ran serially in the assigned worktree with its configured warm target and CARGO_BUILD_JOBS=1.

Command Exit / observation
gh pr view 1849 --json state,mergedAt,mergeCommit 0; MERGED, exact pinned SHA and timestamp above
gh run view 39854120963 --json status,conclusion,headSha and gh run view 39854120965 --json status,conclusion,headSha each 0; completed/success at pinned base
cargo test --manifest-path src-tauri/Cargo.toml --bin projecta api::tests::planning_access_tests::planning_assignment_fence_interleaving_rejects_without_assignment_or_event -- --exact --list 0; one exact test on compiling RED fixture
cargo test --manifest-path src-tauri/Cargo.toml --bin projecta api::tests::planning_access_tests::planning_assignment_fence_interleaving_rejects_without_assignment_or_event -- --exact --nocapture RED 101, then candidate GREEN 0, one test each
cargo test --manifest-path src-tauri/Cargo.toml --bin projecta planning_assignment -- --list 0; two candidate selectors
cargo test --manifest-path src-tauri/Cargo.toml --bin projecta api::tests::planning_access_tests -- --nocapture 0; 20 passed, including four-route Some/None forwarding, scoped restrictions and GOAL/TASK interleavings
cargo test --manifest-path src-tauri/Cargo.toml --bin projecta store::team_assignments::tests -- --nocapture 0; 6 passed
cargo test --manifest-path src-tauri/Cargo.toml --bin projecta api::tests::planning_access_tests::planning_assignment_native_controls_preserve_authority_revision_and_operator -- --exact --nocapture 0 after final assertion readability edits; 1 passed
bash scripts/ci/secret-scan.sh before each normal commit, plus precommit hooks 0; no leaks; both normal commit hooks 0
bash scripts/ci/red-first.sh --plan at candidate 0; count=3, specs=3 (includes repeated RED selector across two commits)
node scripts/ci/architecture-drift.mjs check 0; no new occurrences; main 4058 <= 4059
bash scripts/ci/gates.sh lane prepush at candidate 0; 211 seconds; Rust suite 2326 passed, 7 skipped
git push -u origin codex/m4b-3-assign with normal full prepush hook 0; hook 0, 176 seconds; Rust suite 2326 passed, 7 skipped
git ls-remote origin codex/m4b-3-assign 0; exact candidate SHA
git status --porcelain=v1 / raw git diff --numstat / frozen-test equality check 0; clean tree / 242 raw lines / unchanged semantic test

The targeted planning suite preceded only assertion-readability edits in the sibling control test; that exact control was rerun, and both complete final-head prepush runs cover the final candidate. No source changes followed these runs.

Architecture drift

Replace exactly the existing assignment API_STORE_BLOCK_ON allowlist occurrence with tauri::async_runtime::block_on(self.store.assign_continuous_task_with_authority(authority,task_id,request),). Category/count remain unchanged. This preserves the decided F1 ApiBackend placement and visible production forwarding. Existing assignment types and the goal-list read return type are imported to simplify signatures and keep main below its unchanged ceiling; GOAL/TASK production writers are byte-identical.

Admission and native goal

Own runtime observed 2026-10-22: Codex CLI 0.163.0, provider openai, model gpt-6.1-sol, effort high, assigned worktree. Native weekly usage was 8% at 21:15:20Z and 9% at 21:34:55Z; the npm check alone does not establish provider headroom. Fresh load/RAM/process evidence and npm run dev:start-check -- --max-cargo 2 --min-free-gb 3.5 exited 0 adjacent to build/test/check, commit, gate and push phases; admission samples stayed below load 8 with sufficient RAM and no competing Cargo builds. No workers or reviewers were launched.

Own get_goal returned null; create_goal established the bounded ticket objective, and subsequent get_goal observations kept it active through verified push. Completion is limited to checked worker handover, not Root acceptance. Objective editing is unavailable in the exposed goal API; the bounded objective remains unchanged. AgentsRoom memory/team/usage-overview functions are unavailable in this harness and the local lage-jetzt mirror is absent; live Git/GitHub and own runtime/process evidence were used without inventing native team state.

Root explicitly permitted the pinned base if #1839 landed first. gh pr view 1839 --json state,mergedAt,mergeCommit freshly observed its merge at 2026-10-22T21:22:50Z (5ad970f2814ce251cf86077c4b4a686c1d7a9865). No freshness merge, rebase or history rewrite was performed.

NICHT ABGEDECKT

  • Linux cannot compile or prove #[cfg(windows)] tests (run_in_pty, npm_shim, ConPTY, DPAPI) or Windows Clippy branches. The Windows lane runs in the merge queue.
  • Seven existing Rust tests remain skipped by the suite; this package adds no skipped tests or weakened assertions.
  • Prepush does not provide the full Linux workflow gates, frontend build or browser smoke; external services and desktop usability were not validated. The mandatory hook's existing Denkraum browser tests did run.
  • IMPORT authority enforcement, existing GOAL/security residuals and the separate audit-append crash gap remain outside this package. Continuous stays disabled/frozen.

Reviews and handover

Review: ausstehend (Stufe A).

Required: Root commissions the qualified GLM 5.3 (or permitted 5.3 Flash) and DeepSeek v4.1 Flash reviews from two non-author families, plus a separate GPT observer. No independent review verdict is claimed. Max two rounds; Root owns final merge/split/drop, acceptance, readiness, review-ok and Mergify queueing. Worker does not launch reviews, mark ready or enqueue.

State: implemented, tested, committed and verified pushed; one draft PR is the handover. Independent reviews, Root acceptance, merge and Windows/desktop evidence remain outstanding. IMPORT starts only after actual ASSIGN acceptance/merge and seam release. Parent security goal remains open.

Draft PR: #1852

Tier-A reviews on e341b6f (Root disposition, 2026-10-22 22:10Z)

Reviews via fail-closed sequential review-seq.sh, diff base 8c86bfc, prompt sha256 0e440f50b808950a. glm-5.3:cloud (Zhipu; admission 21:47:12Z load1=1.79; report 21:54:54Z) and deepseek-v4.1-flash:cloud (DeepSeek; admission 21:54:54Z load1=1.58; report 21:57:08Z). Both families differ from the author (OpenAI, gpt-6.1-sol). Both verdicts: approve with conditions. No high finding.

ID Source Severity Finding Disposition
R1852-G1 glm-5.3 medium planning_access.rs:14-16, main.rs import_plan: import writer still authorizes outside its transaction (sibling race) Accepted as condition, out of scope. Tracked as Z4-M4B-4-IMPORT, the next serial package; the M4B security finding is not closed by this PR. IMPORT starts only after this merge.
R1852-G2 glm-5.3 low team_assignments.rs:30-38: #[cfg(test)] assign_continuous_task is an authority-free alias Follow-up (remove or annotate the shim). Not reachable from production builds.
R1852-G3 glm-5.3 low trait default removed on seam, all implementors updated, drift allowlist in lockstep No action (reviewer checked it acceptable).
R1852-G4 / R1852-D1 glm-5.3 low, deepseek medium team_assignments.rs:62-66: every writer refusal maps to the generic PLANNING_REFUSED text, so audit cannot tell self-escalation from a stale fence Rejected as defect, design intent. development_runs.rs:1205 defines PLANNING_REFUSED = "planning target is outside the run project" and :1219 documents "Every refusal is the same PLANNING_REFUSED (no oracle for foreign ids)"; tests therefore correctly assert that exact text. Richer audit cause, if wanted, is a follow-up.
R1852-D2 deepseek medium no HTTP-level test that a coordinator POSTing role: coordinator gets 403 Rejected. planning_access_tests.rs:265 coordinator_cannot_assign_the_coordinator_role asserts 403 over HTTP for "coordinator" and " coordinator "; api.rs:2274 maps PLANNING_REFUSED to 403 (continuous_error).
R1852-D3 deepseek low api/tests/mod.rs: FakeBackend non-native path fabricates success without authority checks Follow-up (fail closed or document that assignment security tests use native_store).

Next: Root marks ready for CI (red-first, linux/windows gates) and reads the GPT observer; review-ok only on this head after both are clean.

CI and GPT observer on e341b6f (Root, 2026-10-22 22:49Z)

All PR checks SUCCESS on e341b6f (red-first, gates linux/windows, linux_1/linux_2, windows_1/windows_2/windows_native, CodeQL, GitGuardian).

ID Source Severity Finding Disposition
C-4354065254 chatgpt-codex-connector (OpenAI observer) P2 docs/PLAN.md:482 vs :571-574: M4B release-order summary still says GOAL is not accepted and TASK follows Follow-up. Confirmed at e341b6f: lines 571-574 predate the #1842 (GOAL) and #1849 (TASK) merges, so the staleness is pre-existing, not introduced here; this package's own PLAN rows are correct. The PLAN owner (Stabschef) refreshes the summary in Z4-M4B-4-IMPORT.

Root acceptance: tier A met (glm-5.3 Zhipu + deepseek-v4.1-flash DeepSeek on this head, both non-author families), no open high finding, conditions recorded (IMPORT next, security finding stays open until IMPORT). review-ok bound to e341b6f.

Cuarroc and others added 2 commits October 22, 2026 23:19
Pause HTTP assignment admission after role and project prechecks, advance the coordinator fence, and require refusal without assignment or event changes. The fixture deliberately delegates to the existing legacy Store writer for the compiling semantic RED.

Test-First: src-tauri/src/api/tests/planning_access_tests.rs::planning_assignment_fence_interleaving_rejects_without_assignment_or_event

Co-authored-by: OpenAI GPT-6.1 <noreply@openai.com>
Acquire the SQLite writer lock before checking run, owner, fence, coordinator role and target project. Reject scoped coordinator-role escalation after normalization, require explicit API authority forwarding, and preserve operator assignments and existing revision and claim controls.

Test-First: src-tauri/src/api/tests/planning_access_tests.rs::planning_assignment_fence_interleaving_rejects_without_assignment_or_event
Test-First: src-tauri/src/api/tests/planning_access_tests.rs::planning_assignment_native_controls_preserve_authority_revision_and_operator

Co-authored-by: GPT-6.1 Sol <noreply@openai.com>
@Cuarroc
Cuarroc marked this pull request as ready for review October 22, 2026 22:06
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-22T22:11:15.067298Z — Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/PLAN.md
| Z4-M4B-1-GOAL | Atomare Autorisierung und Goal/Replan, continuous.rs plus api/planning_access/Tests/main, 220–290 ALL | ein serieller st/api/mn-Owner | Z4-M4B-1a-PLUMB; freigegebene Sicherheitskorrektur ohne Continuous-Aktivierung | eigener Worktree | A | Erledigt: #1842 (merged 2026-10-22T18:35:12Z, fa4f2d9a). Sicherheitsbefund bis Z4-M4B-4-IMPORT offen; Continuous bleibt eingefroren. | deterministisches kompilierendes Fence-Interleaving-Rot; stale ohne Goal/Event; PLANNING_REFUSED muss HTTP 403 und audit_planning mit refused ergeben (eigener deterministischer Rot vor Fix); Alle vier Planungs-POSTs liefern Some(Run/Owner/Fence), Operator explizit None; Scoped Goal-POST erreicht das erforderliche create_continuous_goal_with_authority mit gebundener Run-/Owner-/Fence-Autorität, Operator None; kein ignorierender Produktionsdefault für Goal, kein Goal-Legacy-Routenbypass; Import/Task/Zuweisung behalten ihre Durchreicher bis zum eigenen Paket; scoped control/queue bleiben gesperrt; gültiger Coordinator erfolgreich, autonome Root operator-only, Operator/Audit erhalten; eigene prepush, zwei zulässige Fremdreviews und GPT-Beobachter gemäß AGENTS.md | 2be81e2e |
| Z4-M4B-2-TASK | Atomare Taskanlage, gleicher begrenzter Dateisatz wie GOAL, 180–270 ALL | ein serieller st/api/mn-Owner | Z4-M4B-1-GOAL (Nahtübergabe) | eigener Worktree | A | Erledigt nach Merge dieses Pakets: TASK prüft Run/Owner/Fence/Rolle/Zielprojekt atomar in seiner SQLite-Schreibtransaktion; erforderliche API-Weiterleitung, Operator None erhalten. Eigene prepush ist Pflicht; vor Merge bleiben zwei qualifizierte Fremdvendor-Reviews plus GPT-Beobachter und Root-Abnahme ausstehend. ASSIGN/IMPORT und GOAL-Restbefunde (Ticket 2dbc396c-9b74-4556-9c28-d9e00f5c6310) bleiben offen; Sicherheitsbefund bis IMPORT offen, Continuous bleibt eingefroren. | Fence-Interleaving-Rot; stale ohne Task/Event; eigenes Projekt erfolgreich, fremde Goals/Dependencies abweisen, Operator erhalten; eigene prepush/zwei Fremdreviews | 8dbd5dc7 |
| Z4-M4B-3-ASSIGN | Atomare Zuweisung, team_assignments.rs plus api/planning_access/Tests/main, 200–280 ALL | ein serieller st/api/mn-Owner | Z4-M4B-2-TASK (Nahtübergabe) | eigener Worktree | A | Geplant: strikt seriell (Nutzer 16.10., K7 A; Prüfbericht 16.10.: der Befund gilt weiter); Sicherheitsbefund besteht bis Z4-M4B-4-IMPORT fort, Continuous bleibt eingefroren | Fence-Interleaving-Rot; stale ohne Assignment/Revision/Event; Selbsteskalation abweisen, gültige Zuweisung/Operator erhalten; eigene prepush/zwei Fremdreviews | 15d92066 |
| Z4-M4B-2-TASK | Atomare Taskanlage, gleicher begrenzter Dateisatz wie GOAL, 180–270 ALL | ein serieller st/api/mn-Owner | Z4-M4B-1-GOAL (Nahtübergabe) | eigener Worktree | A | Erledigt: #1849 (merged 2026-10-22T21:03:34Z, `8c86bfc44c50e55209da7de48fdc7e3cb692a750`); TASK prüft Run/Owner/Fence/Rolle/Zielprojekt atomar in seiner SQLite-Schreibtransaktion; erforderliche API-Weiterleitung, Operator None erhalten. IMPORT und GOAL-Restbefunde (Ticket 2dbc396c-9b74-4556-9c28-d9e00f5c6310) bleiben offen; Sicherheitsbefund bis IMPORT offen, Continuous bleibt eingefroren. | Fence-Interleaving-Rot; stale ohne Task/Event; eigenes Projekt erfolgreich, fremde Goals/Dependencies abweisen, Operator erhalten; eigene prepush/zwei Fremdreviews | 8dbd5dc7 |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Synchronize the M4B summary with the completed rows

After this row records M4B-2 as merged, the release-order summary at docs/PLAN.md:571-574 still says GOAL has not been accepted and that TASK follows it, leaving the canonical plan internally contradictory. Update that summary to reflect the merged GOAL/TASK state and the current ASSIGN/IMPORT sequence before approval.

AGENTS.md reference: AGENTS.md:L139-L139

Useful? React with 👍 / 👎.

@Cuarroc Cuarroc added the review-ok Pipeline: review disposition complete, no open high finding label Oct 22, 2026
@Cuarroc

Cuarroc commented Oct 22, 2026

Copy link
Copy Markdown
Owner Author

@Mergifyio queue

@mergify mergify Bot added the queued label Oct 22, 2026
@mergify mergify Bot mentioned this pull request Oct 22, 2026
30 of 46 tasks
@mergify
mergify Bot merged commit 88ef0b7 into main Oct 22, 2026
25 checks passed
@mergify

mergify Bot commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

This pull request spent 13 minutes 17 seconds in the queue, including 12 minutes 37 seconds running CI.

Required conditions to merge
  • check-success = gates (linux)
  • check-success = gates (windows)
  • check-success = red-first
  • github-review-approved [🛡 GitHub repository ruleset rule main-pr-required-checks]
  • label != do-not-merge
  • any of [🛡 GitHub repository ruleset rule main-pr-required-checks]:
    • check-success = @github-actions/gates (linux)
    • check-neutral = @github-actions/gates (linux)
    • check-skipped = @github-actions/gates (linux)
  • any of [🛡 GitHub repository ruleset rule main-pr-required-checks]:
    • check-success = @github-actions/gates (windows)
    • check-neutral = @github-actions/gates (windows)
    • check-skipped = @github-actions/gates (windows)
  • any of [🛡 GitHub repository ruleset rule main-pr-required-checks]:
    • check-success = @github-actions/red-first
    • check-neutral = @github-actions/red-first
    • check-skipped = @github-actions/red-first
  • any of [🛡 GitHub repository ruleset rule main-pr-required-checks]:
    • check-neutral = @mergify/Mergify Merge Protections
    • check-skipped = @mergify/Mergify Merge Protections
    • check-success = @mergify/Mergify Merge Protections

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

Labels

review-ok Pipeline: review disposition complete, no open high finding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant