picatz / picatz/flowstate

policy: the trust, egress, and task-shape policy files are read once at process start and never again; nothing documents that a changed file needs a restart, and no running process can say which policy revision it enforces — the baseline #104's reload seam, #1590's digest, and #1884's change record all assume

Open
#1,891 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

auth documentation enhancement
Dominant language
Go
Stars
9
Forks
0
Avg merge
3h 3m
Merged PRs (30d)
509

Description

Observed behavior

At 7530b29, all three policy surfaces load exactly once, at start, and install process-wide:

  • Task-shape policy: applyTaskPolicy (cmd/flow/taskpolicy.go:55-80) reads the file, parses, and calls v1.SetDefaultTaskPolicy(policy).
  • Egress policy: applyEgressPolicy (cmd/flow/egress.go:167), same shape.
  • Trust policy: read through authFlagsOf (cmd/flow/main.go:205) at command start.

There is no reload path. A search for SIGHUP, fsnotify, reload, or a file watch across cmd/flow, pkg/flowstate/v1/server, and pkg/flowstate/v1 returns nothing outside a generated comment. The assessing pass confirmed the consequence at runtime: a task-policy file changed from allow-all to deny-all during a local run did not affect the running process, which completed; a fresh process refused. The per-attempt enforcement tests (enforcementaudit_test.go:178, the row #1884 cites) replace the policy programmatically through SetDefaultTaskPolicy; they prove per-attempt consultation, not that a deployment file edit reaches a running worker. I confirmed the loading code from source and did not re-run the probe.

The documentation does not say this. docs/DEPLOYMENT.md mentions policy loading only as a startup check that gates readiness (:819, :915) and nowhere states that a changed file is not adopted until restart, or that a rolling restart is the adoption mechanism. The --task-policy doc comment says the fail-open a missing file would cause is "the fail-open this flag exists to prevent"; a file that changed after start is the same fail-open wearing a different face, and an operator who edits the file and sees no refusal has no signal that the edit did nothing.

Three open issues assume a baseline that does not exist yet:

  • #104 designs a reload seam ("workers poll or are pushed the new digest, compile and type-check it before swapping") over the file surface.
  • #1590 wants a policy digest printed at start and carried on audit records, as part of moving the policies to proto.
  • #1884 wants a policy change to be an audit record with digests before and after.

None of the three delivers the smallest present-day contract: what a running process enforces, stated where an operator can read it, and what a file edit does, stated where an operator will look.

Desired outcome

Make the current behavior a stated contract before any of the three builds on it:

  1. docs/DEPLOYMENT.md, in each policy section, states: the file is read once at start; a change is adopted by restarting the process; a rolling restart is how a fleet adopts a change; during the roll, workers enforce different revisions, and the audit trail (once #1590 lands) is how to tell which.
  2. Each process logs, at start, a sha256: digest of each policy file it loaded, beside the existing startup lines, computed over the file bytes today so it does not wait for the proto shape. flow worker and flow server print it; flow run local --egress-policy prints it. This is the "which revision does this worker enforce" answer an operator can join against sha256sum of the file they intended.
  3. A test pins the current behavior on purpose: a policy file rewritten after start does not change enforcement in that process. When #104's reload seam lands, that test changes deliberately rather than the behavior changing silently.

Not in scope: the reload mechanism itself. #104 owns that design and should cite this as its starting condition.

Acceptance criteria

  • docs/DEPLOYMENT.md states the read-once contract for all three files, and the --task-policy, --egress-policy, and --auth-policy flag help text says "read at start".
  • A startup log line per loaded policy file carries the file path and its digest; a test asserts the line and the digest of a known fixture.
  • The pinning test exists for at least the task-shape policy, on both drivers (flow run local and a worker), since invariant 3 applies to the policy model too (#104, "local parity, held the whole way").
  • #104, #1590, and #1884 each cite this issue as the baseline they change.

Constraints and dependencies

  • One digest spelling: sha256: (the spelling #1590 already names). Do not introduce a second.
  • Fail closed is unchanged: a file that fails to parse at start still refuses the command.
  • Adjacent: #104, #1590, #1884, #107 (adoption status is what a control plane would report per worker), #1468 (flow policy explain should print the digest it explained against, which is #1590's acceptance already).

Open questions

  • Whether the digest should also appear in the readiness endpoint so a fleet's adoption state is scrapeable without log access. Cheap, but it exposes a hash of a "crown jewel" file (THREAT_MODEL.md asset 4) to anyone who can reach /healthz; the threat model should decide.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with docs/DEPLOYMENT.md and the loading entry points in cmd/flow/taskpolicy.go, cmd/flow/egress.go, and cmd/flow/main.go. Read the existing startup logging and policy tests, including enforcementaudit_test.go, then verify the documented read-once contract, sha256 startup lines, flag help text, and task-policy pinning tests for local and worker drivers.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
devops, documentation, observability
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.