fix(dispatch): supervisorgroep mag attempt-root doorlopen (M41 T-1948) #96

Merged
janpeter merged 2 commits from fix/m41-broker-attempt-root-group into master 2026-10-02 18:31:31 +02:00
Owner

Waarom

M41 increment 3 (pilot op scrum4me-server) mat een Linux-gat: de broker hield zijn root (DISPATCH_ATTEMPT_OUTPUT_DIR) en elke pogingsmap op root 0700. De supervisor (uid/gid 10001) kreeg EACCES op /run/attempts en kon result.json, transcript en work van geen enkele poging lezen. Daardoor kon geen enkele review slagen. Dit was de open gate "attempt-root read-only mounten is op Linux ongetest". Een operator-ACL helpt niet, want die verandert de groepsbits en dan weigert de startcheck van de broker.

Wat

  • BrokerConfig.attemptGroup (optioneel, geheel getal ≥ 1). Is hij gezet, dan maakt de broker de root en elke pogingsmap root:<attemptGroup> 0710. De groep mag daarmee alleen doorlopen op een exact attempt-id en nooit de map opsommen. Is hij niet gezet, dan blijft alles 0700.
  • De CLI geeft socketGroup door als attemptGroup. Dat is al de expliciet benoemde supervisorgroep, dus er komt geen nieuw autorisatievlak bij.
  • Startcheck assertBrokerRootMode: toegestaan zijn 0700, of 0710 met precies gid = socketGroup. Elke andere groeps- of other-bit, en 0710 met een andere groep, geeft DISPATCH_BROKER_JOURNAL_ACCESS_REFUSED.
  • README en operator-doc zijn bijgewerkt. De regel "Linux confinement not proved" is aangepast: scrum4me-server is bewezen, max2 nog niet.

Bewust ongewijzigd:

  • sources/ blijft 0755 en de sleutelkopie 0644. De supervisor heeft dezelfde uid als het kind, dus de groepsbit opent niets nieuws.
  • Journalbestanden blijven onleesbaar voor de groep.

Bewijs

  • Rood eerst. De nieuwe tests (__tests__/broker-attempt-root-group.test.ts en drie gevallen in dispatch-broker.test.ts) falen tegen de oude code met 4 failures. Met de fix zijn ze groen.
  • Volledige suite. npm test geeft 1035 passed. De 2 bekende macOS-failures in transcript-retention.test.ts (GNU chmod --reference) staan los van deze wijziging. tsc --noEmit -p tsconfig.dispatch.json is groen.
  • Linux, scrum4me-server (pilot-broker op da56399, intake uit):
    • De root ging van root:0 700 naar root:10001 710.
    • Een herstart met die modus wordt geaccepteerd.
    • In de supervisorcontainer geeft stat /run/attempts/<id>/output/result.json nu ENOENT in plaats van EACCES, en readdir /run/attempts blijft EACCES.

Niet bewezen: een volledige poging met echte uitvoer. Dat volgt in M41 increment 4, zodra DISPATCH_ENABLED=1 aan staat.

Story ST-1616, taak T-1948 (Scrum4Me).

🤖 Generated with Claude Code

## Waarom M41 increment 3 (pilot op scrum4me-server) mat een Linux-gat: de broker hield zijn root (`DISPATCH_ATTEMPT_OUTPUT_DIR`) en elke pogingsmap op `root 0700`. De supervisor (uid/gid 10001) kreeg `EACCES` op `/run/attempts` en kon `result.json`, transcript en `work` van geen enkele poging lezen. Daardoor kon geen enkele review slagen. Dit was de open gate "attempt-root read-only mounten is op Linux ongetest". Een operator-ACL helpt niet, want die verandert de groepsbits en dan weigert de startcheck van de broker. ## Wat - `BrokerConfig.attemptGroup` (optioneel, geheel getal ≥ 1). Is hij gezet, dan maakt de broker de root en elke pogingsmap `root:<attemptGroup> 0710`. De groep mag daarmee alleen doorlopen op een exact attempt-id en nooit de map opsommen. Is hij niet gezet, dan blijft alles `0700`. - De CLI geeft `socketGroup` door als `attemptGroup`. Dat is al de expliciet benoemde supervisorgroep, dus er komt geen nieuw autorisatievlak bij. - Startcheck `assertBrokerRootMode`: toegestaan zijn `0700`, of `0710` met precies gid = `socketGroup`. Elke andere groeps- of other-bit, en `0710` met een andere groep, geeft `DISPATCH_BROKER_JOURNAL_ACCESS_REFUSED`. - README en operator-doc zijn bijgewerkt. De regel "Linux confinement not proved" is aangepast: scrum4me-server is bewezen, max2 nog niet. Bewust ongewijzigd: - `sources/` blijft `0755` en de sleutelkopie `0644`. De supervisor heeft dezelfde uid als het kind, dus de groepsbit opent niets nieuws. - Journalbestanden blijven onleesbaar voor de groep. ## Bewijs - **Rood eerst.** De nieuwe tests (`__tests__/broker-attempt-root-group.test.ts` en drie gevallen in `dispatch-broker.test.ts`) falen tegen de oude code met 4 failures. Met de fix zijn ze groen. - **Volledige suite.** `npm test` geeft 1035 passed. De 2 bekende macOS-failures in `transcript-retention.test.ts` (GNU `chmod --reference`) staan los van deze wijziging. `tsc --noEmit -p tsconfig.dispatch.json` is groen. - **Linux, scrum4me-server** (pilot-broker op `da56399`, intake uit): - De root ging van `root:0 700` naar `root:10001 710`. - Een herstart met die modus wordt geaccepteerd. - In de supervisorcontainer geeft `stat /run/attempts/<id>/output/result.json` nu `ENOENT` in plaats van `EACCES`, en `readdir /run/attempts` blijft `EACCES`. Niet bewezen: een volledige poging met echte uitvoer. Dat volgt in M41 increment 4, zodra `DISPATCH_ENABLED=1` aan staat. Story ST-1616, taak T-1948 (Scrum4Me). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(dispatch): supervisorgroep mag attempt-root doorlopen (M41 T-1948)
All checks were successful
CI / Compose config (pull_request) Successful in 5s
CI / Build-arg coverage (pull_request) Successful in 12s
CI / Docker build (pull_request) Successful in 1m14s
da56399b8d
Op scrum4me-server gemeten: de broker hield zijn root en elke pogingsmap
op root 0700, dus de supervisor (uid/gid 10001) kreeg EACCES op
/run/attempts en kon result.json, transcript en work van geen enkele
poging lezen. De broker maakt root en pogingsmap nu root:<socketGroup>
0710 (alleen doorlopen op exact id, nooit een lijst); de startcheck
staat precies die groeps-x-bit toe. Zonder groep blijft alles 0700.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
s4m-codex-reviewer requested changes 2026-10-02 18:15:58 +02:00
Dismissed
s4m-codex-reviewer left a comment

REQUEST_CHANGES

  • BLOCKER — bin/run-dispatch-runtime-broker.ts:50: assertBrokerRootMode maskeert alleen 0o077. Daardoor wordt een root met bijvoorbeeld mode 0600 geaccepteerd, terwijl het gedocumenteerde en beoogde contract uitsluitend 0700 of 0710 (met exact socketGroup) toestaat. Valideer de volledige permissiemodus (mode & 0o777) en voeg regressietests toe voor ongeldige owner-bits zoals 0600.

Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden.

## REQUEST_CHANGES - **BLOCKER — bin/run-dispatch-runtime-broker.ts:50:** `assertBrokerRootMode` maskeert alleen `0o077`. Daardoor wordt een root met bijvoorbeeld mode `0600` geaccepteerd, terwijl het gedocumenteerde en beoogde contract uitsluitend `0700` of `0710` (met exact `socketGroup`) toestaat. Valideer de volledige permissiemodus (`mode & 0o777`) en voeg regressietests toe voor ongeldige owner-bits zoals `0600`. Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden.
fix(dispatch): broker-rootcheck vergelijkt de volledige modus (review #96)
All checks were successful
CI / Compose config (pull_request) Successful in 4s
CI / Build-arg coverage (pull_request) Successful in 11s
CI / Docker build (pull_request) Successful in 1m21s
dc5b87fc60
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Owner

BLOCKER verwerkt in dc5b87f: assertBrokerRootMode vergelijkt nu de volledige modus (mode & 0o7777): alleen exact 0700, of 0710 met gid = socketGroup. Regressietests rood-eerst toegevoegd voor 0600, 0500, 0610, 0o1700, 0o2710 en 0o4700 (vóór de fix faalde 0600). Volledige suite 1035 passed (2 bekende macOS-failures in transcript-retention); tsc groen. Op scrum4me-server herstart de pilot-broker op dc5b87f correct met root root:10001 710.

BLOCKER verwerkt in `dc5b87f`: `assertBrokerRootMode` vergelijkt nu de volledige modus (`mode & 0o7777`): alleen exact `0700`, of `0710` met gid = `socketGroup`. Regressietests rood-eerst toegevoegd voor `0600`, `0500`, `0610`, `0o1700`, `0o2710` en `0o4700` (vóór de fix faalde `0600`). Volledige suite 1035 passed (2 bekende macOS-failures in transcript-retention); tsc groen. Op scrum4me-server herstart de pilot-broker op `dc5b87f` correct met root `root:10001 710`.
s4m-codex-reviewer left a comment

APPROVED

Findings

  • Geen blokkerende of error-severity findings gevonden in de aangeleverde diff. De root- en attempt-directorymodi worden expliciet gevalideerd, de permissiewijziging is afgedekt met regressietests, en de operator- en README-documentatie zijn bijgewerkt.

Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden.

## APPROVED ### Findings - Geen blokkerende of error-severity findings gevonden in de aangeleverde diff. De root- en attempt-directorymodi worden expliciet gevalideerd, de permissiewijziging is afgedekt met regressietests, en de operator- en README-documentatie zijn bijgewerkt. Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden.
janpeter merged commit 38922410f9 into master 2026-10-02 18:31:31 +02:00
Sign in to join this conversation.
No reviewers
No labels
severity/s3
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
janpeter/scrum4me-docker!96
No description provided.