fabro/lib/crates/fabro-workflow/src/handler
fabro-sh-0530[bot] 59a4afa188
Make run actors and provenance total; remove Principal::Anonymous (#463)
## Summary

Removes `Principal::Anonymous` as an actor variant and makes run
creator/provenance non-optional across the full stack — Rust types,
OpenAPI schema, generated TypeScript client, and frontend components.
Every persisted run now has a mandatory creator; there are no nullable
`created_by`, `provenance`, or `subject` fields anywhere in the system.

As a separate cleanup, all `cargo` invocations in CI and dev tooling
gain `--locked` to prevent unintended dependency resolution drift.

### Plan Summary

- **Commit 1 – Remove `Principal::Anonymous`**:
`RequestAuthContext.principal` becomes `Option<Principal>`; `initial()`
and `rejected()` set `None`; all auth gate helpers match on
`Option<Principal>`; HTTP log computes `principal_kind` as
`principal.as_ref().map_or("none", Principal::kind)`;
`PrincipalAnonymous` removed from the OpenAPI schema and generated
client; frontend `principalDisplay` drops the `"anonymous"` case.

- **Commit 2 – Total provenance**: `RunProvenance.subject`,
`RunSpec.provenance`, `Run.created_by`, and `RunCreatedProps.provenance`
all become non-optional. `Default` derive dropped from `RunProvenance`.
Demo mode gets a synthetic `DEMO_PRINCIPAL` via `AuthMethod::DevToken`.
A new `fabro-types` `test-support` feature exports `test_principal()`
and `test_run_provenance()` used across all affected crates and TS
tests. All `provenance: None` / `created_by: null` literals in tests are
replaced with the test fixture.

- **`--locked` CI hardening**: Every `cargo` invocation in GitHub
Actions workflows and `fabro-dev` tooling commands now passes
`--locked`.

### Key design decisions

- `None` principal (unauthenticated / rejected requests) is now
structurally distinct from any actor variant — no sentinel value that
could accidentally pass actor checks.
- `RunProvenance` no longer implements `Default` because a provenance
with no subject is incoherent; callers must supply a real actor at
construction time.
- The `cancel_run` handler was refactored as part of this change to
correctly handle in-process blocked runs: a new test
(`cancel_durably_blocked_in_process_run_cancels_pending_interview_without_abort_signal`)
covers the cancellation path that should let the workflow unwind rather
than aborting it.
- Test fixtures live under the existing `test-support` feature flag
pattern; no fake-auth helpers were added to the `fixtures` module.


### Fabro Details

<details>
<summary>Ran 9 stages in 129m 57s for $53.54</summary>

| Stage | Duration | Cost | Retries |
|---|---|---|---|
| start | 0s | – | 0 |
| toolchain | 1s | – | 0 |
| preflight_compile | 2m 10s | – | 0 |
| preflight_lint | 2m 22s | – | 0 |
| implement | 76m 55s | $47.53 | 0 |
| simplify_opus | 14m 46s | $3.21 | 0 |
| simplify_gpt | 2m 26s | $1.04 | 0 |
| verify | 14m 44s | – | 0 |
| fixup | 15m 43s | $1.76 | 0 |
| **Total** | **129m 57s** | **$53.54** | **0** |

</details>

<details>
<summary>Ran <code>ImplementPlan.fabro</code> (11 nodes and 14
edges)</summary>

```dot
digraph ImplementPlan {
    graph [
        goal="Implement and simplify",
        model_stylesheet="
            * { model: claude-opus-4-7; }
        "
    ]
    rankdir=LR

    start [shape=Mdiamond, label="Start"]
    exit  [shape=Msquare, label="Exit"]

    toolchain         [label="Toolchain", shape=parallelogram, script="command -v cargo >/dev/null || { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && sudo ln -sf $HOME/.cargo/bin/* /usr/local/bin/; }; cargo --version 2>&1", max_retries=0]
    preflight_compile [label="Preflight Compile", shape=parallelogram, script="cargo check -q --workspace 2>&1", max_retries=0]
    preflight_lint    [label="Preflight Lint", shape=parallelogram, script="cargo +nightly-2026-04-14 clippy -q --workspace --all-targets -- -D warnings 2>&1", max_retries=0]
    fix_lints         [label="Fix Lints", prompt="The preflight lint step failed. Read the build output from context and fix all clippy lint warnings.", max_visits=3]
    implement         [label="Implement", prompt="Read the plan file referenced in the goal and implement every step. Make all the code changes described in the plan. Use red/green TDD.", model="gpt-55", reasoning_effort="xhigh"]
    simplify_opus     [label="Simplify (Opus)", prompt="@prompts/simplify.md"]
    simplify_gpt      [label="Simplify (GPT-55)", prompt="@prompts/simplify.md", model="gpt-55"]
    verify            [label="Verify", shape=parallelogram, script="git fetch origin main 2>&1 && git merge --no-edit --no-stat origin/main 2>&1 && cargo +nightly-2026-04-14 fmt --all 2>&1 && cargo dev docs refresh 2>&1 && cargo +nightly-2026-04-14 fmt --check --all 2>&1 && { command -v rg >/dev/null 2>&1 || { echo 'rg is required for verify'; exit 127; }; } && ! rg -n 'AuthMode::Disabled|RunAuthMethod|RunSubjectProvenance|\bActorRef\b|\bActorKind\b|AuthenticatedSubject|AuthenticatedService|AuthorizeRunScoped|AuthorizeRunBlob|AuthorizeStageArtifact|AuthorizeCommandLog|auth_method\s*==\s*\"disabled\"' lib/crates apps lib/packages docs/public/api-reference/fabro-api.yaml 2>&1 && cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D warnings 2>&1 && cargo nextest run --workspace --status-level slow --profile ci 2>&1 && cargo dev docs check 2>&1 && bun install --frozen-lockfile 2>&1 && (cd apps/fabro-web && bun run typecheck) 2>&1 && (cd apps/fabro-web && bun run test) 2>&1 && (cd lib/packages/fabro-api-client && bun run typecheck) 2>&1 && cargo dev build -- -p fabro-cli --release 2>&1", goal_gate=true, retry_target="fixup"]
    fixup             [label="Fixup", prompt="The verify step failed. Read the build output from context and fix all format, clippy, Rust test, docs, TypeScript typecheck/test, and build failures.", max_visits=3]

    start -> toolchain
    toolchain -> preflight_compile [condition="outcome=succeeded"]
    toolchain -> exit
    preflight_compile -> preflight_lint [condition="outcome=succeeded"]
    preflight_compile -> exit
    preflight_lint -> implement [condition="outcome=succeeded"]
    preflight_lint -> fix_lints
    fix_lints -> preflight_lint
    implement -> simplify_opus -> simplify_gpt -> verify
    verify -> exit  [condition="outcome=succeeded"]
    verify -> fixup
    fixup -> verify
}

```

</details>

⚒️ Generated with [Fabro](https://fabro.sh)

---------

Co-authored-by: fabro-sh-0530[bot] <281434857+fabro-sh-0530[bot]@users.noreply.github.com>
Co-authored-by: Fabro <noreply@fabro.sh>
Co-authored-by: Bryan Helmkamp <19+brynary@users.noreply.github.com>
Co-authored-by: Release Repro <release-repro@example.com>
2026-05-31 11:18:01 -04:00
..
llm Make run actors and provenance total; remove Principal::Anonymous (#463) 2026-05-31 11:18:01 -04:00
agent.rs Make run actors and provenance total; remove Principal::Anonymous (#463) 2026-05-31 11:18:01 -04:00
command.rs Make run actors and provenance total; remove Principal::Anonymous (#463) 2026-05-31 11:18:01 -04:00
conditional.rs refactor(workflow): update stage outcome semantics 2026-04-30 06:06:51 -04:00
exit.rs refactor(workflow): update stage outcome semantics 2026-04-30 06:06:51 -04:00
fan_in.rs Fix stage inference/tool timing reporting (was always zero) (#408) 2026-05-25 21:57:40 -04:00
human.rs Migrate sandbox config to named environments; add InterviewOption metad… (#372) 2026-05-23 15:47:33 -04:00
manager_loop.rs Migrate sandbox config to named environments; add InterviewOption metad… (#372) 2026-05-23 15:47:33 -04:00
mod.rs Add output_schema validation with same-context repair for agent and pro… (#374) 2026-05-23 19:45:16 -04:00
parallel.rs Make run actors and provenance total; remove Principal::Anonymous (#463) 2026-05-31 11:18:01 -04:00
prompt.rs Make run actors and provenance total; remove Principal::Anonymous (#463) 2026-05-31 11:18:01 -04:00
start.rs refactor(workflow): update stage outcome semantics 2026-04-30 06:06:51 -04:00
structured_output.rs Add output_schema validation with same-context repair for agent and pro… (#374) 2026-05-23 19:45:16 -04:00
wait.rs refactor(workflow): update stage outcome semantics 2026-04-30 06:06:51 -04:00