Every row below maps a real-world failure mode to the control that this repository actually implements, and to the unit test that proves it. A row exists here only because the code and the test exist — no speculative defences, no claimed mechanisms without evidence.
The chain for every row is:
Failure → Control → Evidence
↑ ↑
implementation test (file:test)
| Failure Mode | Detection | Default Response | Recovery | Data Safety | Evidence |
|---|---|---|---|---|---|
| Duplicate request | Idempotency key + payload hash | Reject on conflict, otherwise safe replay of stored result | Replay from store | Protected | TestExecuteRetryReturnsStoredResult, TestExecuteSameKeyDifferentPayloadConflicts |
| Transient dependency failure | Error classification (Retryable) |
Retry with exponential backoff + jitter | Backoff then succeed | Preserved | TestRetryRetriesUntilSuccess, TestRetryExhausts |
| Persistent dependency failure | Failure threshold counter | Fail fast (ErrOpen) |
Half-open probe recovery | Preserved | TestOpensAfterThreshold, TestHalfOpenProbeSucceedsCloses, TestHalfOpenProbeFailsReopens |
| Invalid signature | HMAC-SHA256 verification | Reject (ErrInvalidKey / ErrInvalidSignature) |
None (re-issue key / re-sign) | Protected | TestVerifyRejectsTamperedKey, TestVerifyRejectsWrongSecret, TestVerifyRejectsTamperedPayload, TestVerifyRejectsGarbageSignature |
| Rate-limit exhaustion | Token-bucket state | Reject (Allow returns false) |
Wait for refill | Preserved | TestAllowConsumesTokens, TestRefill |
| Audit-chain mismatch | Hash-chain verification | Fail closed (Verify returns false) |
Investigate the trail | Protected | TestTamperDetected, TestChainLinks, TestAppendAndVerify |
| Webhook duplication | Replay nonce + signature | Deduplicate (reject seen nonce) / reject forged signature | Replay-safe delivery | Protected | TestValidateRejectsDuplicateNonce, TestSignVerifyRoundTrip |
- Implementation:
reliability/idempotency/gateway.go:34—Gateway.Executeclaims the key viaStore.TryClaim(reliability/idempotency/idempotency.go:60), which binds the key to a SHA-256 payload hash. A completed key returns the stored response without re-running the operation; the same key with a different payload returnsErrConflict(reliability/idempotency/idempotency.go:18). - Tests:
TestExecuteFirstCallRunsOp,TestExecuteRetryReturnsStoredResult(op runs exactly once),TestExecuteSameKeyDifferentPayloadConflicts,TestHashDeterministic. - Data safety: Protected — payload identity is bound to the key, so a key cannot silently absorb a different request.
- Implementation:
reliability/retry/retry.go:45—RetryhonoursConfig.Retryableto classify failures; transient errors sleep exponential backoff (retry.go:69) with jitter and a cappedMaxDelay; a non-retryable error returns immediately; exhausted attempts joinErrExhausted(reliability/retry/retry.go:38). - Tests:
TestRetryRetriesUntilSuccess(3 attempts, succeeds),TestRetryStopsOnNonRetryable(exactly 1 call),TestRetryExhausts(exactlyMaxAttemptscalls). - Data safety: Preserved — nothing is committed while an attempt is failing.
- Implementation:
reliability/circuitbreaker/breaker.go:47—Breakeropens afterFailureThresholdconsecutive failures,Allowfails fast withErrOpen(breaker.go:16), a cooldown moves toHALF-OPENwhere a probe decides (Succeedcloses afterSuccessThreshold; a probe failure reopens).Execute(breaker.go:108) wraps any downstream call. - Tests:
TestOpensAfterThreshold,TestHalfOpenProbeSucceedsCloses,TestHalfOpenProbeFailsReopens. - Data safety: Preserved — load is shed before downstream mutations can cascade.
- Implementation:
security/auth/auth.go:56—Issuer.Verifyrecomputes the HMAC-SHA256 signature with constant-timehmac.Equal; tampered or foreign-signed keys yieldErrInvalidKey. For webhook payloads,webhook/webhook.go:17—Verifydecodes the hex signature, recomputes the HMAC, and rejects withErrInvalidSignature. - Tests:
TestVerifyRejectsTamperedKey,TestVerifyRejectsWrongSecret(auth);TestVerifyRejectsWrongSecret,TestVerifyRejectsTamperedPayload,TestVerifyRejectsGarbageSignature(webhook); positive controlsTestMintVerifyRoundTrip,TestSignVerifyRoundTrip. - Data safety: Protected — rejection happens before any state change.
- Implementation:
security/ratelimit/ratelimit.go:39—AllowNrefills the bucket from elapsed time atratetokens/sec, caps atcapacity, and denies when insufficient tokens remain.Allowconsumes one token. - Tests:
TestAllowConsumesTokens(burst of 2, third denied),TestAllowN(bulk tokens),TestRefill. - Data safety: Preserved — denied requests never reach the operation.
- Implementation:
observability/audit/audit.go:47—Appendlinks each entry to the previous entry's hash;Verify(audit.go:77) recomputes every hash and re-linksPrevHash, returningfalseon any mutation.EnforceAppendOnly(audit.go:99) additionally rejects non-monotonic sequences. - Tests:
TestAppendAndVerify,TestTamperDetected,TestChainLinks,TestEnforceAppendOnly. - Data safety: Protected — a tampered trail is detectable, not silently trusted.
- Implementation:
webhook/webhook.go:17authenticates the delivery (HMAC-SHA256);reliability/replay/replay.go:53—Guard.Validaterejects a replayed nonce (dedup by event identity) and out-of-window timestamps withErrReplay. Together: a replayed delivery cannot carry a forged signature, and a captured delivery cannot be re-sent within the replay window. - Tests:
TestSignVerifyRoundTrip,TestVerifyRejectsTamperedPayload(webhook);TestValidateRejectsDuplicateNonce,TestValidateRejectsExpired,TestValidateRejectsFutureSkew,TestValidateAllowsDifferentNoncesSameTime(replay). - Data safety: Protected — deduplicated and authenticated before any processing.
- A row is only listed if
go test ./...exercises its control (all evidence columns are real test names from this repository). - The matrix asserts what the mechanism does, not that every deployment
configures it. Wiring (
reliability/replay) and key distribution are the operator's responsibility. - Recovery is stated as implemented:
replayrejects and requires a fresh nonce; it does not retry on its own.
- To add a failure mode: implement the control, add the test, then add the row
with the exact test name and
package/file.go:lineof the implementation. - To change behavior: update the test first, then the row — the matrix must never describe behavior the tests do not prove.
docs/architecture.md— flow and state-machine diagrams for the core controls.README.md— package-by-package failure-mode/defence index.