← all branches

fix/mrr-base

needs attentionviewing older commit
e807453 · incrementalpre-PRreviewed 2026-08-11 19:07 UTC0H · 2M · 3L · 8I
The branch
Purpose
Fix gaps in the PostHog annotation pipeline (MRR credit model + deploy trigger gate)
Goal
Ensure deploy annotations fire for ALL behavioral prod promotions (CDK/DB/Tinybird-only, not just Vercel), with self-describing DEPLOY_LANES metadata; fix MRR credit model under-reporting base-fee orgs
Sub-goals
  • SG-1: Broaden posthog-annotate trigger from vercel-only to any behavioral lane
  • SG-2: Add DEPLOY_LANES env to make each marker self-describing (partial vs full promote)
  • SG-3: Explicitly exclude posthog-apply as annotation trigger (analytics config ≠ deploy)
  • SG-4: Fix MRR credit model base_price drop (earlier commit, last reviewed)
The changes (whole branch)
What
This incremental: workflow `posthog-annotate` job condition broadened from `vercel-promote == success` to `(vercel-promote OR cdk-deploy OR db-migrate OR tinybird-prod) == success`; DEPLOY_LANES env added; annotation script renders lanes in content; rule SSOT updated to match
Why
A CDK-only or Tinybird-only prod promotion previously produced no annotation marker, making those deploys invisible on PostHog charts — the gap that motivated this fix
Areas
.claude/rules/posthog-annotations.md+166.github/workflows/release-promote.yml+152scripts/posthog-annotate.mjs+80
Blast
3 files, +39/−8 total on branch; scripts and CI only — no domain logic, no DB, no API surface
ci-workflow-change analytics-config
CI (no PR)· No open PR for this branch — CI rollup unavailableCodeRabbit· No .coderabbit.yaml in repo

Findings · 11

correctness4

medium

DEPLOY_LANES space-concatenation relies on script normalization to be safe

.github/workflows/release-promote.yml

Lanes are joined with trailing spaces ('cdk ', 'db ', etc.) in the >- block scalar, then the script does `.trim().replace(/\s+/g, ', ')` to normalize. This works today but the correctness contract is split across two files — if a future lane is added without the trailing space, or the script's normalization changes, the output silently breaks. Low runtime risk right now (trim/replace handles all whitespace permutations), but the design is fragile.

low

posthog-apply exclusion is implicit via `needs` list absence

.github/workflows/release-promote.yml

posthog-apply is correctly excluded because it's absent from posthog-annotate's `needs` array (so its result is never reachable in the if-condition). This is correct, but if someone later adds posthog-apply to `needs` for ordering (e.g., a future sequencing requirement), its result would silently become available without being in the condition. The rule documents this exclusion clearly, which mitigates the risk.

info

!cancelled() guard correctly allows annotation after partial-cancellation

.github/workflows/release-promote.yml

Without !cancelled(), the job would skip if the workflow was cancelled after a lane already succeeded. The guard correctly allows the annotation to fire in partial-cancellation scenarios — intentional per the 'marker fires even if post-flight health was red' design.

info

>- block scalar correctly produces space-separated lane tokens

.github/workflows/release-promote.yml

The folded-strip scalar folds newlines into spaces and strips trailing newlines. Each ${{ }} expression on the same logical line is concatenated. Result is a single whitespace-separated string like 'cdk db vercel tinybird' or any subset. The script's normalize handles it correctly.

security2

info

DEPLOY_LANES contains only hardcoded workflow literals — zero injection surface

.github/workflows/release-promote.yml

DEPLOY_LANES is assembled from GitHub Actions ternary expressions over job result strings (GitHub-controlled enum values). The four token values ('cdk ', 'db ', 'vercel ', 'tinybird') are string literals in the workflow YAML — no user input, PR title, branch name, or external data flows in.

info

Job permissions are minimal (contents: read only)

.github/workflows/release-promote.yml

posthog-annotate job declares only contents: read. No id-token, no packages, no PR write. The override correctly scopes down from the workflow-level id-token: write.

conventions1

info

Rule SSOT updated in sync with code — correct pattern

.claude/rules/posthog-annotations.md

The rule, script, and workflow were updated together in the same commit. DEPLOY_LANES env var name is consistent between workflow (`DEPLOY_LANES:`) and script (`process.env.DEPLOY_LANES`). posthog-apply is absent from the if-condition. continue-on-error: true is preserved. All non-negotiables intact.

tests1

info

No unit tests for DEPLOY_LANES — consistent with project conventions for scripts/

scripts/posthog-annotate.mjs

The new DEPLOY_LANES transform is two trivial lines. No test files exist for any posthog-*.mjs script, consistent with project norms for this layer. Workflow condition changes are not unit-testable. No coverage gap.

improvement3

medium

Adding a new lane requires updating two places: if-condition AND DEPLOY_LANES

.github/workflows/release-promote.yml

The job's `if` condition and the `DEPLOY_LANES` env var both enumerate the same four lanes (cdk-deploy, db-migrate, vercel-promote, tinybird-prod). When a new behavioral lane is added, a developer must update both without structural enforcement. A set-lanes step that emits `has_deployments` + `lanes` outputs would make both consumers derive from one source. Current approach is DRY-violating at the workflow level.

low

Whitespace normalization contract between workflow and script is undocumented

scripts/posthog-annotate.mjs

The script's `.replace(/\s+/g, ', ')` silently corrects the workflow's space-separated token format. A comment (`// DEPLOY_LANES is space-separated from CI; normalize to comma-separated`) would make this coupling explicit and prevent a future caller from being surprised that the normalization happens here rather than at the source.

low

No DEPLOY_LANES allowlist — unexpected values appear verbatim in annotation

scripts/posthog-annotate.mjs

The script trusts DEPLOY_LANES verbatim after whitespace normalization. A simple allowlist check (known values: cdk, db, vercel, tinybird) with warn-and-continue would make annotation content more reliable without adding failure risk. Low priority since the workflow only ever sets hardcoded string literals.

History · 4 commits

  1. 2db5192needs attentionincremental0H · 4M · 5L2026-08-11 22:54
  2. 1a8164fneeds attentionincremental2H · 2M · 4L2026-08-11 22:46
  3. e807453needs attentionincremental0H · 2M · 3L2026-08-11 19:07current
  4. 69a0691needs attentionfull3H · 7M · 5L2026-08-11 18:12