Skip to content

fix(store): make task planning authorization atomic (M4B-2) - #1849

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

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

Conversation

@Cuarroc

@Cuarroc Cuarroc commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Die Taskanlage prüft die Koordinatorberechtigung jetzt innerhalb derselben SQLite-Schreibtransaktion erneut.
Ein deterministischer HTTP-Test belegt die bisherige Fence-Lücke und ihre Abweisung ohne neuen Task oder Event.
Continuous bleibt deaktiviert und eingefroren; unabhängige Reviews und Root-Abnahme stehen noch aus.

Report

Plan-ID: Z4-M4B-2-TASK

Change and delivery

  • Base: 5a07fc0895ff6bb813df265fa9d730d38d1b1ed9; candidate: af8226f8ab06982e038e957a0398de290dbf85c0 on codex/m4b-2-task.
  • Raw merge-base diff: 239 lines (212 additions + 27 deletions), nine authorized files, including all tests and both PLAN rows. No dependency or migration changes.
  • create_continuous_task_with_authority reuses require_planning_authority with PlanningTarget::Goal after begin_goal_task_audit obtains BEGIN IMMEDIATE, before task normalization and domain writes. Authority checks, task/event writes, savepoint rollback and the goal/task audit share that writer transaction.
  • The task backend method is required. ApiBackend explicitly forwards authority; the obsolete legacy API method is removed. The legacy Store convenience wrapper is test-only and passes explicit None; operator HTTP writes also reach the required method with None.
  • GOAL production implementation and ASSIGN/IMPORT authority adapters are byte-identical to the base, verified by bounded source-section comparison. Later writers remain open. PLAN changes are restricted to GOAL's verified merge status and TASK's conditional post-merge boundary/duties.
  • Implemented, locally verified and pushed; submitted as draft for review. Root owns acceptance, readiness and Mergify integration. No successor ASSIGN dispatch is implied.

Semantic red-first and test boundary

Regression: api::tests::planning_access_tests::planning_task_fence_interleaving_rejects_without_task_or_event in src-tauri/src/api/tests/planning_access_tests.rs.

The public HTTP boundary uses the existing FakeBackend.native_store fixture with real SQLite role/project prechecks and task writes. A bounded test-only admission handshake pauses after those real prechecks. An independent SQLite connection advances the coordinator fence before releasing writer admission. Both receives are time-bounded; unwinding disconnects the resume sender before scoped joins. No sleeps or production test hook were added.

  • Compiling semantic RED: frozen 5a07fc08 production plus the finalized test overlay recorded in cbd8a2e039427709db2678c2b0e3f1ae76ea260f; production-source diff against the base was empty (exit 0). The RED fixture overrides the already existing authority method but delegates to the legacy Store writer. The exact test ran and exited 101, observing HTTP 200, a newly created task and an accepted planning envelope instead of 403/refused. No missing-selector result is used as semantic evidence.
  • GREEN at the candidate: the same exact test exits 0, with 403/refused and unchanged public task/event snapshots. The complete test file is byte-identical to the finalized RED overlay: SHA-256 50f69238d6c0eb04ea2f2a2abab67e2dd7b5be9731bc8cb972e790df6176844f. The only GREEN fixture change is delegation to the new authority-aware Store entry point with the real authority.
  • The same regression proves successful own-project creation after fence restoration and successful operator creation, then foreign-goal refusal (403) and foreign-dependency refusal (404) without partial own-project task/event changes. Task snapshots use public Store::continuous_context(project, 0).tasks; events use public continuous_changes. SQL is used for boundary setup/fence mutation and the existing audit-read pattern.
  • The existing native planning-envelope control now performs real task creation, provisions its root ledger and verifies the additional task_create audit alongside the two planning envelopes.

Evidence (2026-10-22, Linux)

All Cargo invocations and heavy phases ran serially in this package's worktree. Resource admission preceded heavy phases: fresh UTC/load/RAM/cargo observations, load below 8, available RAM above 3500 MiB, no existing cargo build at admission; npm run dev:start-check -- --max-cargo 2 --min-free-gb 3.5 exited 0. Actual native harness reported gpt-6.1-sol, effort high; observed weekly utilization remained below the implementation cap.

Command Exit / observation
cargo test --manifest-path src-tauri/Cargo.toml --bin projecta api::tests::planning_access_tests::planning_task_fence_interleaving_rejects_without_task_or_event -- --list 0; exactly one listed selector
cargo test --manifest-path src-tauri/Cargo.toml --bin projecta api::tests::planning_access_tests::planning_task_fence_interleaving_rejects_without_task_or_event -- --exact --nocapture RED 101 on unchanged production + finalized overlay; GREEN 0 on candidate, one test passed
cargo test --manifest-path src-tauri/Cargo.toml --bin projecta api::tests::planning_access_tests -- --nocapture 0; 18 passed, including GOAL atomicity, four-route authority delivery and scoped control/queue denial
cargo test --manifest-path src-tauri/Cargo.toml --bin projecta store::continuous::tests -- --nocapture 0; 28 passed, including root budget/deadline/scope, rollback, audit and one-connection invariants
bash scripts/ci/gates.sh lane prepush 0 at af8226f, 278 s; 2324 Rust tests passed, 7 existing skips
git push -u origin codex/m4b-2-task 0, normal full prepush hook 0 at af8226f, 176 s; 2324 Rust tests passed, 7 existing skips; 1707 frontend tests passed
git ls-remote origin refs/heads/codex/m4b-2-task refs/heads/main 0; candidate exactly af8226f; main still 5a07fc0
bash scripts/ci/red-first.sh --plan 0 at candidate; count=3, specs=3 (same exact regression trailer on the three commits)
node scripts/ci/architecture-drift.mjs check 0; no new occurrence; all four seam ceilings preserved
bash scripts/ci/secret-scan.sh 0 before every commit; normal precommit hooks also 0
git diff --check 5a07fc08...HEAD 0
gh run view 39837362146 --json headSha,status,conclusion 0; completed/success at exact base, rechecked after push

Architecture drift

Replace exactly the existing task API_STORE_BLOCK_ON allowlist occurrence with the authority-aware call. This preserves the decided F1 location of ApiBackend until after M4; no new category, occurrence or ceiling. Main remains 4059/4059 lines; API shrinks to 2554/2574. No warning suppression was added.

Review and remaining ownership

Review: ausstehend (Stufe A).

Root commissions two qualified non-OpenAI vendor reviews (glm-5.3 or permitted glm-5.3-flash, plus deepseek-v4.1-flash) and a separate Codex observer, bound to af8226f8ab06982e038e957a0398de290dbf85c0. No independent review is claimed and the author launched none. Findings/dispositions: pending; Root retains the two-round merge/split/drop decision and review-ok/queue authority.

Parent: Z4/M4B atomic scoped planning authorization. Ticket: 8dbd5dc7-7de2-4eea-bdcd-b98d14a93365; execution owner: srv-m4b-2-task. This bounded handover delivers TASK; the parent remains open. Dependencies GOAL #1842 and base #1835 are merged. Next: qualified reviews and Root acceptance, then Mergify; later ASSIGN/IMPORT stay separate. Residual GOAL review inventory remains open in ticket 2dbc396c-9b74-4556-9c28-d9e00f5c6310.

NICHT ABGEDECKT

  • Linux does not compile/run #[cfg(windows)] tests (run_in_pty, npm_shim, ConPTY, DPAPI) or Windows clippy branches. The Windows lane runs in the merge queue; this is only Linux evidence.
  • The prepush lane does not cover the separate linux-lane browser smoke/frontend build/workflow gates; external updater/router/mirror service state is not proven.
  • The HTTP fixture uses real SQLite through the existing fake backend boundary. A real desktop AppHandle/runtime launch was not exercised. The stronger authority-check-to-insert window pinning experiment was not performed or claimed.
  • Full automated red-first replay was not run locally; --plan, explicit selector listing and the compiling semantic RED/GREEN runs above are the observed evidence.
  • Planning envelopes remain appended after the domain transaction; that existing crash gap is unchanged. ASSIGN/IMPORT races and residual GOAL inventory remain open. Overall scoped-planning security is not closed; Continuous remains disabled/frozen.

Review round 1 — Root disposition (2026-10-22T19:57Z, head af8226f, base 5a07fc0)

Tier A (seams api.rs, main.rs, store/). Author family OpenAI (gpt-6.1-sol). Reviewers: glm-5.3 (Zhipu) approve with conditions, deepseek-v4.1-flash (DeepSeek) approve with conditions; no high. Size 212+/27- = 239 lines (≤300). PLAN rows: Z4-M4B-1-GOAL now "Erledigt: #1842", Z4-M4B-2-TASK "Erledigt nach Merge…" — both parse as valid statuses (parseGoals; the 8 pre-existing invalid rows are unchanged).

ID Source Sev Finding Disposition
R1849-G1 glm-5.3 F1 medium Assignment/import writers still discard authority no change: by design, own packages Z4-M4B-3-ASSIGN / Z4-M4B-4-IMPORT; the overall security finding stays open (PLAN row says so)
R1849-G2 / R1849-D1 glm-5.3 F2, deepseek F1 low/medium Stale-fence refusal audited with the cross-project text PLANNING_REFUSED follow-up (ticket 2dbc396c, same as R1842-G3/D2): shared constant from #1607 used by every planning refusal
R1849-G3 / R1849-D5 glm-5.3 F3, deepseek F5 low Removed trait method / test-only store writer: non-test callers or other implementors? rejected: git grep at af8226f finds no non-test caller of create_continuous_task( (incl. bin/pa.rs) and exactly three impl ControlBackend (main.rs:2574, api/tests/mod.rs:690, api/agent_access.rs:657), all updated; prepush runs cargo clippy --all-targets (gates.sh:206), exit 0
R1849-G4 / R1849-D2 glm-5.3 F4, deepseek F2 low Atomicity depends on the writer lock being taken up front rejected: begin_goal_task_audit → begin_write uses BEGIN IMMEDIATE (store/continuous.rs:1168)
R1849-G5 glm-5.3 F5 low ApiBackend forwarding in main.rs has no direct test follow-up (same pass-through shape as #1836/#1842; route delivery is covered through FakeBackend)
R1849-D3 deepseek F3 low FakeBackend now routes tasks to the real store when native_store is set — whole api module green? rejected: own prepush exit 0 at af8226f, 2324 Rust tests passed
R1849-D4 deepseek F4 low Operator case may use the scoped descriptor rejected: server.descriptor_path() is the server's operator API descriptor (api.rs:1096), same pattern as api/tests/mod.rs:2229; asserting task.goalId there too is a low follow-up

No accepted code finding → no NACHBESSERN round. Next: PR checks, GPT observer (codex bot) on af8226f, then acceptance.

GPT observer + acceptance — Root, 2026-10-22T20:11Z, head af8226f

ID Source Sev Finding Disposition
R1849-B1 codex bot 4352930619 (planning_access_tests.rs:648) P1 A source-changing commit lacks a red-first trailer rejected: all three commits (cb554b3, cbd8a2e, af8226f) carry Test-First: src-tauri/src/api/tests/planning_access_tests.rs::planning_task_fence_interleaving_rejects_without_task_or_event; tf_message_has_required_trailer (scripts/lib/test-first.sh:54, origin/main) returns 0 for each; CI red-first SUCCESS on af8226f
R1849-B2 codex bot 4352930631 (docs/PLAN.md:482) P2 TASK row still says the vendor reviews are outstanding follow-up: the row is written as the post-merge state ("Erledigt nach Merge dieses Pakets"); the pre-merge clause is corrected by the next serial package (Z4-M4B-3-ASSIGN updates the TASK row, as TASK did for GOAL). No push on a reviewed seam head for a wording-only change

PR checks on af8226f: all green (gh pr checks --watch exit 0). Tier A met: glm-5.3 (Zhipu) + deepseek-v4.1-flash (DeepSeek), no high, no accepted code finding; GPT observer dispositioned. Root decision: merge. The overall M4B security finding stays open until Z4-M4B-4-IMPORT.

Cuarroc and others added 3 commits October 22, 2026 21:22
Prove the public HTTP precheck-to-writer fence race against unchanged production code. Delegate the existing native fixture to the legacy Store task writer before the fix.

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

Co-authored-by: GPT-6.1 Sol <noreply@openai.com>
Compare the complete public task snapshot after fixture setup has advanced the coordinator fence. Preserve the writer admission handshake and refusal assertions; the unchanged production writer still accepts the stale request. Also name the real task_create audit action in the native fixture control.

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

Co-authored-by: GPT-6.1 Sol <noreply@openai.com>
Recheck scoped planning authority under the existing goal/task writer lock before task writes. Require explicit task authority forwarding in the API backend, keep operator None and GOAL semantics, and leave assignment/import adapters unchanged.

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

Co-authored-by: GPT-6.1 Sol <noreply@openai.com>
@Cuarroc
Cuarroc marked this pull request as ready for review October 22, 2026 19:57
@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-22T20:01:23.918456Z af8226f 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.

Reviewed commit: af8226f8ab

ℹ️ 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 on lines +647 to +648
#[test]
fn planning_task_fence_interleaving_rejects_without_task_or_event() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add the required red-first trailer

This source-changing commit adds the regression test but contains no Test-First:, Regression-For:, or No-Test: trailer (tf_message_has_required_trailer rejects its message), so the red-first gate cannot associate or replay the claimed failing test and the commit is not mergeable under the repository workflow. Add the exact test selector as a Test-First: trailer.

AGENTS.md reference: AGENTS.md:L268-L271

Useful? React with 👍 / 👎.

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 nach Merge von #1842: atomarer GOAL-Schreiber geliefert; vor Merge bleiben Fremdreviews und Root-Abnahme ausstehend. 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 | 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 Task/Event; eigenes Projekt erfolgreich, fremde Goals/Dependencies abweisen, Operator erhalten; eigene prepush/zwei Fremdreviews | 8dbd5dc7 |
| 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 |

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 Bring the TASK plan status up to date

At this reviewed head, the recorded review disposition says the two vendor reviews have completed, but this row still says both vendor reviews are outstanding. Because docs/PLAN.md is the canonical dispatch state, leaving that claim here can cause the coordinator to schedule duplicate reviews and prevents the required head status from being accurate before review-ok; update the row to distinguish the completed vendor reviews from the still-pending GPT observation and Root acceptance.

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 8c86bfc 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 52 minutes 13 seconds in the queue, including 51 minutes 42 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