Scanner PoE Dev Harness

Audience: Scanner and Signer developers validating the PoE-to-Signer contract on a local workstation. This is a development harness, not a production or CI procedure — see Boundaries.

This runbook exercises Scanner Worker Proof-of-Exposure (PoE) against the real Signer service in local compose. It is opt-in and does not enable PoE in the default development stack.

What It Proves

Prerequisites

Fast Path

Use the local dev Authority client:

powershell -ExecutionPolicy Bypass -File .\devops\compose\scripts\scanner-poe-dev.ps1 -Action config -NoTokenFetch -PrintEnvironment
powershell -ExecutionPolicy Bypass -File .\devops\compose\scripts\scanner-poe-dev.ps1 -Action up

Run the deterministic Signer smoke against live local services:

powershell -ExecutionPolicy Bypass -File .\devops\compose\scripts\scanner-poe-dev.ps1 -Action smoke

To persist the Signer response for a later DSSE/Finding-bundle review, provide an output path. To bind the smoke predicate to a Findings evidence bundle, provide the regenerated bundle hash:

powershell -ExecutionPolicy Bypass -File .\devops\compose\scripts\scanner-poe-dev.ps1 `
  -Action smoke `
  -BundleHash "sha256:<findings bundle hash>" `
  -OutputResponsePath .\artifacts\signer-poe-findings-bundle-response.json

The script writes or reuses a local ES256 DPoP private key at devops/compose/offline/scanner-poe-dev/dpop-es256-private.pem when the local PowerShell/.NET runtime supports PEM import/export. Older Windows PowerShell runtimes fall back to an ephemeral ES256 key for that run and print a warning. In both cases it uses one key for the Authority and Signer proofs, retries once with a nonce claim when Authority returns DPoP-Nonce, derives a fresh Signer DPoP proof for POST /api/v1/signer/sign/dsse with ath over the access token, computes SCANNER_POE_WORKER_IMAGE_DIGEST from Docker, and injects the resulting environment into:

The default entitlement token key is dev_poe instead of dev-poe because the Signer container starts through a POSIX shell entrypoint. Environment variable names containing hyphens are discarded by that shell before dotnet starts.

-Action up starts local Authority first when it must mint a token, starts Signer with the trusted local Scanner digest, runs the deterministic DSSE smoke against Signer, and only then starts Scanner Worker with PoE:Enabled=true. -BundleHash is optional for the base Scanner-to-Signer smoke, but should be used when the response is evidence for a concrete Findings bundle. The hash is included in the signed predicate; Findings verification still validates the downloaded bundle hash independently before accepting the DSSE envelope.

For offline compose rendering without live Authority, use either an explicit token or no-fetch config rendering:

$env:SCANNER_POE_BEARER_TOKEN = "<access token with signer:sign>"
powershell -ExecutionPolicy Bypass -File .\devops\compose\scripts\scanner-poe-dev.ps1 -Action config -PrintEnvironment

powershell -ExecutionPolicy Bypass -File .\devops\compose\scripts\scanner-poe-dev.ps1 -Action config -NoTokenFetch -PrintEnvironment

The second command uses placeholder auth values only to render compose configuration. Do not use it for up or smoke.

Manual Compose

If you do not use the helper, set these values yourself:

$env:SCANNER_POE_WORKER_IMAGE_DIGEST = "sha256:<docker image id for stellaops/scanner-worker:dev>"
$env:SCANNER_POE_BEARER_TOKEN = "<access token with signer:sign>"
$env:SCANNER_POE_DPOP_PROOF = "<DPoP proof for POST http://signer.stella-ops.local:8441/api/v1/signer/sign/dsse>"

Then run:

cd .\devops\compose
docker compose `
  -f docker-compose.stella-infra.yml `
  -f docker-compose.stella-services.yml `
  -f docker-compose.scanner-poe-dev.yml `
  up -d signer scanner-worker

Expected Failure Modes

Boundaries

This is a development harness, not a release manifest substitute. The local Docker image ID is enough to test the Scanner-to-Signer contract in dev. A release pipeline must still use registry manifest digests and deployment-managed Authority clients, DPoP key custody, and secret distribution. The committed scanner-poe-dev client secret is local/dev fixture material only and must not be reused in CI, staging, production, or shared environments.