Skip to content

feat(synthetic): money/value-journey legs + CI→NR emit (Wave 5)#95

Merged
mastermanas805 merged 3 commits into
masterfrom
ci/wave5-nr-ci-event-and-money-journeys
Jun 6, 2026
Merged

feat(synthetic): money/value-journey legs + CI→NR emit (Wave 5)#95
mastermanas805 merged 3 commits into
masterfrom
ci/wave5-nr-ci-event-and-money-journeys

Conversation

@mastermanas805

Copy link
Copy Markdown
Member

Wave 5 of the CI integration plan (docs/ci/01-CI-INTEGRATION-DESIGN.md). Two additive pieces, both flag/secret-gated and inert by default.

1) Generalize the prod synthetic monitor to money/value journeys

flow_synthetic_money.go adds four legs to the continuous flow matrix, each reading a TRUTH SURFACE (rule 12), run by the SAME 5-min flow_synthetic job under the SAME FLOW_SYNTHETIC_ENABLED master flag + per-flow kill list, emitting the SAME instant_flow_test_* counters + InstantFlowTest event (cohort=synthetic):

  • claimGET /claim/preview invalid-token → assert 400 invalid_token contract (anon→claimed funnel; single-use-preserving).
  • deploy_statusPOST /deploy/new → assert tier-gate 402 wall on a no-headroom tier (or 201 + reap on headroom, rule 24).
  • checkoutPOST /api/v1/billing/checkout → assert non-5xx reachability (contract-only; Razorpay live operator-blocked).
  • magic_linkPOST /auth/email/start (202) THEN read forwarder_sent.classification (rule 12 — a rejected classification, the Brevo-unvalidated-sender reality, FAILS the leg; the 202 alone is NOT a delivery).

Work() mints the session JWT once and shares it across the P0 + money matrices. flow_synthetic_money_test.go + extended flow_synthetic_test.go give 100% patch coverage of the new file. Flag-off no-op proven.

2) CI test-run → NR emit

.github/actions/nr-ci-event (mirrors api/web) wired into ci.yml build-and-test + integration as if:always(). No-ops cleanly without the NR secret.

Verify

  • Per-package go test ./internal/jobs/ -short GREEN; flow tests pass deterministically (4/4 runs). 100% patch coverage on flow_synthetic_money.go + flow_synthetic.go.
  • Pre-existing flake flagged: the full go test ./... -p 1 run has an intermittent jobs-package flake (River "PeriodicJobEnqueuer: context canceled" teardown race, ~1/3 runs, unrelated to these hermetic httptest+sqlmock flow tests). Per memory feedback_coverage_measure_per_package_not_dotdotdot the authoritative gate is CI.

Operator action

Provision NEW_RELIC_LICENSE_KEY + NEW_RELIC_ACCOUNT_ID as GitHub secrets on the worker repo; enable the synthetic suite per infra/FLOW-SYNTHETIC-RUNBOOK.md (FLOW_SYNTHETIC_ENABLED=true).

Companion PRs (Wave 5)

🤖 Generated with Claude Code

Wave 5 of the CI integration plan (docs/ci/01-CI-INTEGRATION-DESIGN.md).
Two additive pieces, both flag/secret-gated and inert by default.

1) Generalize the prod synthetic monitor to the money/value journeys.
flow_synthetic_money.go adds four legs to the continuous flow matrix, each
reading a TRUTH SURFACE (CLAUDE.md rule 12), run by the SAME 5-min
flow_synthetic River job under the SAME FLOW_SYNTHETIC_ENABLED master flag +
per-flow FLOW_SYNTHETIC_DISABLED kill list, emitting the SAME
instant_flow_test_* counters + InstantFlowTest event (cohort=synthetic):
  - claim         — GET /claim/preview invalid-token → assert 400 invalid_token
                    contract (anon→claimed funnel step; single-use-preserving).
  - deploy_status — POST /deploy/new → assert the tier-gate 402 wall on a
                    no-headroom tier (or 201 + reap on a headroom tier, rule 24).
  - checkout      — POST /api/v1/billing/checkout → assert non-5xx reachability
                    (contract-only; Razorpay live recurring operator-blocked).
  - magic_link    — POST /auth/email/start (202) THEN read forwarder_sent
                    .classification (rule 12 — a 'rejected' classification, the
                    Brevo-unvalidated-sender reality, FAILS the leg; the 202
                    alone is NOT a delivery).
Work() mints the session JWT once and shares it across the P0 + money matrices.
flow_synthetic_money_test.go + extended flow_synthetic_test.go give 100% patch
coverage of the new file (every contract/error/degraded branch, the headroom
deploy create→reap + reap-leak/transport-error paths, the classifier seam).
Inert when FLOW_SYNTHETIC_ENABLED is unset (the flag-off no-op test proves it).

2) CI test-run → New Relic emit (reusable composite action).
.github/actions/nr-ci-event POSTs InstantCITestRun (always) + InstantCITestFailure
(on fail) to the NR Event API; wired into ci.yml build-and-test + integration as
an if:always() step. No-ops cleanly without NEW_RELIC_LICENSE_KEY/ACCOUNT_ID.

Per-package `go test ./internal/jobs/ -short` GREEN; the flow tests pass
deterministically. NOTE: the full `go test ./... -p 1` run has a PRE-EXISTING
intermittent flake in the jobs package (River "PeriodicJobEnqueuer: context
canceled" teardown race, ~1/3 runs, unrelated to these hermetic httptest+sqlmock
flow tests) — per memory feedback_coverage_measure_per_package_not_dotdotdot the
authoritative gate is CI.

Operator action: provision NEW_RELIC_LICENSE_KEY + NEW_RELIC_ACCOUNT_ID as GitHub
secrets on the worker repo; enable the synthetic suite per
infra/FLOW-SYNTHETIC-RUNBOOK.md (FLOW_SYNTHETIC_ENABLED=true).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 enabled auto-merge (squash) June 5, 2026 23:50
mastermanas805 and others added 2 commits June 6, 2026 05:25
…ses them as inputs

The nr-ci-event composite action referenced github.*/secrets.*/job.status in its
own env: block; GitHub rejects those inside a composite action. Move resolution
to the caller's with: block; action reads only inputs.*. Adds event-name + actor
inputs; callers pass repo/workflow/branch/commit-sha/log-url/event-name/actor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GitHub evaluates ${{ }} expressions even inside an input's description: string,
so the example 'Pass ${{ secrets.NEW_RELIC_LICENSE_KEY }}' text in the
descriptions triggered the same Unrecognized-named-value validation error. Use
plain backtick-quoted text in all descriptions; only the runs: body keeps
inputs.* expressions (the one context a composite action may read).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 merged commit 9a508db into master Jun 6, 2026
12 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