Skip to content

HIPAA PR1: provision audit signing secret for security-audit + worker - #48

Merged
man4ish merged 1 commit into
mainfrom
security/hipaa-audit-signing-secret-provisioning
Aug 14, 2026
Merged

HIPAA PR1: provision audit signing secret for security-audit + worker#48
man4ish merged 1 commit into
mainfrom
security/hipaa-audit-signing-secret-provisioning

Conversation

@man4ish

@man4ish man4ish commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Problem

The audit-signing implementation exists in omnibioai-security-audit (signing helper, integrity classification, EVENT_SIGNING_SECRET), but the signing component was not receiving the correctly provisioned secret in this repository's deployed configuration. Both security-audit and security-audit-worker were missing JWT_SECRET in docker-compose.yml, so:

  • security-audit's own JWT verification (api/deps.py::require_platform_admin, audit/identity.py::validate_identity_token)
  • AuditConfig.EVENT_SIGNING_SECRET (audit/config.py, os.getenv("JWT_SECRET", "change-me")), which the worker's classify_event_integrity() uses to verify audit-event signatures

both silently fell back to the public literal "change-me" instead of the real platform secret.

Fix

Both services now receive JWT_SECRET: ${AUTH_SECRET_KEY:-change-me} — the exact same variable name and value every other JWT_SECRET consumer in this compose file already uses (api-gateway, control-center, tes, and others; auth-service itself signs with the equivalent SECRET_KEY). No new variable was introduced and no secret value was added to source — AUTH_SECRET_KEY is sourced from .env, which is gitignored and untracked, exactly as it already is for every existing consumer.

Verified live prior to this commit, by hash comparison only (no value ever printed): security-audit's JWT_SECRET, security-audit-worker's JWT_SECRET, and auth-service's SECRET_KEY all hash identical inside their running containers.

Security impact

This enables the existing audit-event signing/verification mechanism in omnibioai-security-audit to operate with the intended platform signing secret instead of a public default. It is a prerequisite for making audit integrity operational — without it, once a producer starts signing events (a later PR), the worker would verify against the wrong secret and misclassify every legitimately signed event as invalid.

Scope

This PR is provisioning only. It explicitly does not implement:

  • audit producer signing
  • audit database migration
  • audit classification
  • audit verification pipeline changes
  • TES work_dir isolation
  • GHCR remediation
  • release/deployment changes

Each of the above is a separate, later PR per the planned sequence (PR2: DB/schema deployment, PR3: producer signing, PR4: TES isolation).

Validation

docker compose -f docker-compose.yml config --quiet          → exit 0
pytest tests/ (excl. integration)                             → 97 passed
pytest tests/test_compose_release_config.py
       tests/test_compose_network_exposure.py                 → 71 passed (unaffected — cover the release compose files, not this one)
node --test tests/test_secret_generation.js                   → 13 passed

git diff reviewed: docker-compose.yml only, two services (security-audit, security-audit-worker), both additions match the file's own established JWT_SECRET pattern exactly.

🤖 Generated with Claude Code

Problem: security-audit and security-audit-worker never received JWT_SECRET
in this compose file, so two things silently fell back to the public
literal "change-me" instead of the real platform secret:

  - security-audit's own JWT verification (api/deps.py::require_
    platform_admin, audit/identity.py::validate_identity_token)
  - AuditConfig.EVENT_SIGNING_SECRET (audit/config.py:34,
    os.getenv("JWT_SECRET", "change-me")), which PR2's
    classify_event_integrity() uses to verify audit-event signatures

Fix: both services now receive JWT_SECRET: ${AUTH_SECRET_KEY:-change-me},
the exact same variable name/value every other JWT_SECRET consumer in
this file already uses (auth-service's own SECRET_KEY, api-gateway,
control-center, tes, ...). No new variable introduced, no secret value
added to source -- AUTH_SECRET_KEY is sourced from .env (gitignored,
untracked) exactly as it already is for every other consumer.

Verified live prior to this commit (hash comparison only, values never
printed): security-audit's JWT_SECRET, security-audit-worker's
JWT_SECRET, and auth-service's SECRET_KEY all hash identical inside
their running containers.

Scope: this is provisioning only. It does not add producer-side signing,
run the audit-integrity DB migration, touch audit classification/
verification code, address TES work_dir isolation, or touch GHCR/release
tooling -- each is a separate, later PR.

Validation:
  - docker compose -f docker-compose.yml config --quiet: exit 0
  - pytest tests/ (excl. integration): 97 passed
  - pytest tests/test_compose_release_config.py
    tests/test_compose_network_exposure.py: 71 passed (unaffected --
    these cover the release compose files, not this one)
  - node --test tests/test_secret_generation.js: 13 passed
  - git diff reviewed: docker-compose.yml only, two services, both
    additions match the file's own established JWT_SECRET pattern

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@man4ish
man4ish merged commit 4941877 into main Aug 14, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant