STORY-F-005: Bitwarden finnest project + GitHub Actions ci-finnest.yml¶
Epic: Infrastructure Priority: Must Have Story Points: 2 Status: Not Started Assigned To: Unassigned Created: 2026-04-17 Sprint: 1
User Story¶
As the Lead Developer, I want Finnest secrets living in Bitwarden Secrets Manager (carry-forward from AgenticAI-app) and CI running on every push via GitHub Actions on the existing bastion runners, so that secrets never live in git (SE-07, SE-12) and every commit is compile-checked, format-checked, Credo-checked, Dialyzer-checked, boundary-checked, and test-suite-checked before merge.
Description¶
Background¶
ADR-014-F §Reuse inventory commits to Bitwarden Secrets Manager (same org, new finnest project) and GitHub Actions runners on the existing CI bastion (13.236.155.22). No new infrastructure needed — reuse AgenticAI-app's proven pattern.
This story bootstraps both. No deployment yet (F-011 adds Kamal to integration); this is compile + test + lint in CI.
Scope¶
In scope:
- Bitwarden SM admin action: create
finnestproject in the AgenticAI organisation's Bitwarden; create machine account; generate access token - Seed initial secrets (values set by ops):
FINNEST_DB_PASSWORD(local dev)FINNEST_SECRET_KEY_BASE(Phoenix session signing)FINNEST_CLOAK_KEY_V1(application-level encryption, generated viamix phx.gen.secret)ANTHROPIC_API_KEY(for F-013)SMSGLOBAL_API_KEY,SMSGLOBAL_API_SECRET(reuse AgenticAI-app credentials initially)scripts/deploy-finnest.sh— mirror of AgenticAI-appscripts/deploy.sh— usesbwsCLI to fetch secrets before invoking Kamal (Kamal itself wired in F-011).github/workflows/ci-finnest.yml— runs on every push to any branch + PR to main:- Checkout
- Setup Elixir + Erlang via
erlef/setup-beam@v1matching.tool-versions - Cache
_build+deps mix deps.get --only prodfor prod check,mix deps.getfor dev/testmix format --check-formattedMIX_ENV=prod mix compile --warnings-as-errorsmix credo --strictmix dialyzer(with cached PLT)mix test --covermix sobelow --config(SE-11)mix deps.audit(SE-11)mix boundary(AR-08, added after F-002 exists)gitleaksstep (SE-12)- Tag runner label to pin to CI bastion runners (
runs-on: [self-hosted, linux, ci-bastion]) - Document
bwssetup inCLAUDE.mdaddendum (developer onboarding)
Out of scope:
- Kamal deploy config (F-011)
- Production deployment workflow (F-020)
- IRAP-specific pipeline (Phase 3, not this PRD scope)
- Dependency soak / Renovate configuration (F-020 or Phase 1)
Technical Notes¶
- Bitwarden SM access: Gautham has Org admin; create
finnestproject via Bitwarden web UI orbws project create - Machine account token format:
BWS_ACCESS_TOKEN=0.xxx.yyy. Store in GitHub Actions secretBWS_FINNEST_TOKEN - CI runners on bastion already have
bwsbinary installed (carry-forward from AgenticAI-app); verify withwhich bws - Dialyzer PLT cache key:
${{ runner.os }}-plt-${{ hashFiles('**/mix.lock') }} mix test --coverreports coverage to stdout; fail if below 80% (CQ-02 — but first few sprints may have lower coverage, so don't fail on coverage in Sprint 1; add threshold gate in F-020 or Phase 1)- Secrets are NOT injected into CI test runs — tests use Mock adapters (F-013) / factories / deterministic seeds. CI secret access is only for deploy workflows (F-011/F-020).
Dependencies¶
- Blocked by: STORY-F-001 (umbrella + mix.exs must exist for deps to resolve), STORY-F-002 (boundary dep)
- Blocks: STORY-F-011 (deploy scripts assume this pattern)
Acceptance Criteria¶
- Bitwarden
finnestproject visible in Bitwarden SM web UI - Machine account token created; stored as GitHub Actions secret
BWS_FINNEST_TOKENon theMMGS-Softnet-Pty-Ltd/finnest-planningrepo (migrate tofinnestcode repo when that exists) -
scripts/deploy-finnest.shscript exists;scripts/deploy-finnest.sh --helpprints usage;--dry-runflag works without invoking Kamal -
.github/workflows/ci-finnest.ymlexists; triggers on push + PR - First CI run succeeds: compile, format, credo, dialyzer, test all green
- CI run time: <5 min target on clean clone; <2 min on warm cache
- Deliberate test: push a
mix formatviolation → CI fails (demonstrate, then revert) - Deliberate test: push a Credo strict violation → CI fails (demonstrate, then revert)
-
gitleaksstep catches a deliberate fake-secret commit in a feature branch (demonstrate, then revert) - Documentation: brief section in repo
CLAUDE.mdon "Running CI locally" + "Adding a new secret"
Testing Requirements¶
- CI workflow tested by opening a PR with a trivial change; all steps pass
- Deliberate-failure tests above prove each gate actually blocks on violation
- Secret-rotation dry-run: change
FINNEST_SECRET_KEY_BASEin Bitwarden; re-runscripts/deploy-finnest.sh --dry-run; confirm new value is fetched (bws picks up the update)
References¶
../adrs/adr-014-F-infrastructure-reuse-from-agenticai-app.md§Implementation Plan steps 1, 6- AgenticAI-app
scripts/deploy.sh,docs/secrets-management.md(reference patterns) ../10-GUARDRAILS.mdSE-07, SE-11, SE-12, SE-16, IN-06, IN-13, IN-14