Skip to main content

MC #105153 — API write bucket stage E2E rate-limit override

MC #105153 — Bilko API write bucket 429 stage E2E

Scope

Fix authenticated api rate-limit bucket 429s on stage E2E for sentinel contact create and instant-demo write-protection probes, while preserving production defaults.

Changes verified on disk

  • apps/api/src/main/kotlin/no/alai/bilko/plugins/RateLimit.kt
    • Added apiRateLimitConfig(perMinuteEnv) parser.
    • RateLimitName("api") now uses API_RATE_LIMIT_PER_MINUTE with default 100.
  • apps/api/src/test/kotlin/no/alai/bilko/plugins/RateLimitTest.kt
    • Added tests for default 100, stage override 500, invalid fallback 100.
  • azure-pipelines.yml
    • Stage ACA deploy sets API_RATE_LIMIT_PER_MINUTE=500 for bilko-api-stage.
  • .github/workflows/azure-stage.yml
    • Stage ACA deploy sets API_RATE_LIMIT_PER_MINUTE=500.
  • .env.example
    • Documents API_RATE_LIMIT_PER_MINUTE, AUTH_RATE_LIMIT_PER_MINUTE, DEMO_RATE_LIMIT_PER_MINUTE, DEMO_RATE_LIMIT_PER_HOUR defaults.
  • infrastructure/gcp/ENV-MATRIX.md
    • Documents stage-only API_RATE_LIMIT_PER_MINUTE=500; demo/prod default/absent.

Verification — 2026-07-09T23:07Z

Command run from apps/api:

./gradlew test --tests no.alai.bilko.plugins.RateLimitTest --rerun-tasks

Result: BUILD SUCCESSFUL in 21s, 7 actionable tasks: 7 executed.

JUnit XML evidence:

apps/api/build/test-results/test/TEST-no.alai.bilko.plugins.RateLimitTest.xml
<testsuite name="no.alai.bilko.plugins.RateLimitTest" tests="22" skipped="0" failures="0" errors="0" ...>

Static presence check:

grep -n "API_RATE_LIMIT_PER_MINUTE" \
  apps/api/src/main/kotlin/no/alai/bilko/plugins/RateLimit.kt \
  apps/api/src/test/kotlin/no/alai/bilko/plugins/RateLimitTest.kt \
  azure-pipelines.yml .github/workflows/azure-stage.yml \
  infrastructure/gcp/ENV-MATRIX.md .env.example

Observed paths/lines:

  • apps/api/src/main/kotlin/no/alai/bilko/plugins/RateLimit.kt:115
  • apps/api/src/main/kotlin/no/alai/bilko/plugins/RateLimit.kt:125
  • azure-pipelines.yml:527
  • .github/workflows/azure-stage.yml:181
  • infrastructure/gcp/ENV-MATRIX.md:36
  • .env.example:70

Production-safety note

Production default remains unchanged: absent/invalid API_RATE_LIMIT_PER_MINUTE resolves to 100, and only stage deploy config sets API_RATE_LIMIT_PER_MINUTE=500.

P2P pre-verifier

  • PASS: mesh-thr-77df628b-c7b4-4c5e-a3ff-1825826bb7f9 / mesh-msg-f642fa23-cb94-476f-af4b-01a63f386be2
  • Evidence JSON: /tmp/alai/company-mesh-auto-responder/2026-07-09T23-10-17-743Z-mesh-msg-f1bd06a1-d6a6-4b9d-84b8-e60304ecfc39.json