hatch3r 1.7.1 → 1.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +37 -11
  2. package/agents/hatch3r-a11y-auditor.md +4 -0
  3. package/agents/hatch3r-architect.md +4 -0
  4. package/agents/hatch3r-ci-watcher.md +4 -0
  5. package/agents/hatch3r-context-rules.md +4 -0
  6. package/agents/hatch3r-creator.md +4 -0
  7. package/agents/hatch3r-dependency-auditor.md +4 -0
  8. package/agents/hatch3r-devops.md +4 -0
  9. package/agents/hatch3r-docs-writer.md +4 -0
  10. package/agents/hatch3r-fixer.md +4 -0
  11. package/agents/hatch3r-handoff-loader.md +243 -0
  12. package/agents/hatch3r-handoff-preparer.md +134 -0
  13. package/agents/hatch3r-implementer.md +4 -0
  14. package/agents/hatch3r-learnings-loader.md +4 -0
  15. package/agents/hatch3r-lint-fixer.md +4 -0
  16. package/agents/hatch3r-perf-profiler.md +8 -0
  17. package/agents/hatch3r-researcher.md +4 -0
  18. package/agents/hatch3r-reviewer.md +92 -0
  19. package/agents/hatch3r-security-auditor.md +24 -0
  20. package/agents/hatch3r-test-writer.md +4 -0
  21. package/agents/modes/requirements-elicitation.md +4 -1
  22. package/agents/modes/similar-implementation.md +6 -0
  23. package/agents/modes/user-flows.md +76 -0
  24. package/agents/shared/quality-charter.md +128 -0
  25. package/commands/hatch3r-board-fill.md +1 -0
  26. package/commands/hatch3r-create.md +2 -0
  27. package/commands/hatch3r-handoff.md +126 -0
  28. package/commands/hatch3r-pr-resolve.md +4 -0
  29. package/commands/hatch3r-quick-change.md +4 -2
  30. package/commands/hatch3r-workflow.md +2 -0
  31. package/dist/cli/index.js +2321 -460
  32. package/dist/cli/index.js.map +1 -1
  33. package/package.json +4 -2
  34. package/rules/hatch3r-accessibility-standards.md +21 -0
  35. package/rules/hatch3r-accessibility-standards.mdc +21 -0
  36. package/rules/hatch3r-agent-orchestration.md +9 -1
  37. package/rules/hatch3r-agent-orchestration.mdc +9 -1
  38. package/rules/hatch3r-ai-evals.md +158 -0
  39. package/rules/hatch3r-ai-evals.mdc +154 -0
  40. package/rules/hatch3r-ai-ux-patterns.md +131 -0
  41. package/rules/hatch3r-ai-ux-patterns.mdc +127 -0
  42. package/rules/hatch3r-api-design.md +67 -9
  43. package/rules/hatch3r-api-design.mdc +67 -9
  44. package/rules/hatch3r-api-versioning.md +119 -0
  45. package/rules/hatch3r-api-versioning.mdc +115 -0
  46. package/rules/hatch3r-auth-patterns.md +170 -0
  47. package/rules/hatch3r-auth-patterns.mdc +166 -0
  48. package/rules/hatch3r-component-conventions.md +30 -0
  49. package/rules/hatch3r-component-conventions.mdc +30 -0
  50. package/rules/hatch3r-container-hardening.md +131 -0
  51. package/rules/hatch3r-container-hardening.mdc +127 -0
  52. package/rules/hatch3r-contract-testing.md +117 -0
  53. package/rules/hatch3r-contract-testing.mdc +113 -0
  54. package/rules/hatch3r-deep-context.md +2 -0
  55. package/rules/hatch3r-deep-context.mdc +2 -0
  56. package/rules/hatch3r-dependency-management.md +73 -1
  57. package/rules/hatch3r-dependency-management.mdc +72 -0
  58. package/rules/hatch3r-design-system-detection.md +142 -0
  59. package/rules/hatch3r-design-system-detection.mdc +138 -0
  60. package/rules/hatch3r-event-schema-evolution.md +90 -0
  61. package/rules/hatch3r-event-schema-evolution.mdc +86 -0
  62. package/rules/hatch3r-handoff-readiness.md +45 -0
  63. package/rules/hatch3r-handoff-readiness.mdc +40 -0
  64. package/rules/hatch3r-i18n.md +13 -0
  65. package/rules/hatch3r-i18n.mdc +13 -0
  66. package/rules/hatch3r-migrations.md +61 -16
  67. package/rules/hatch3r-migrations.mdc +61 -16
  68. package/rules/hatch3r-observability-logging.md +1 -1
  69. package/rules/hatch3r-observability-logging.mdc +1 -1
  70. package/rules/hatch3r-observability-metrics.md +1 -1
  71. package/rules/hatch3r-observability-metrics.mdc +1 -1
  72. package/rules/hatch3r-observability-tracing-detail.md +1 -1
  73. package/rules/hatch3r-observability-tracing-detail.mdc +1 -1
  74. package/rules/hatch3r-observability-tracing.md +1 -1
  75. package/rules/hatch3r-observability-tracing.mdc +1 -1
  76. package/rules/hatch3r-observability.md +1 -0
  77. package/rules/hatch3r-observability.mdc +1 -0
  78. package/rules/hatch3r-operability.md +149 -0
  79. package/rules/hatch3r-operability.mdc +145 -0
  80. package/rules/hatch3r-passkey-server.md +181 -0
  81. package/rules/hatch3r-passkey-server.mdc +177 -0
  82. package/rules/hatch3r-progressive-delivery.md +120 -0
  83. package/rules/hatch3r-progressive-delivery.mdc +116 -0
  84. package/rules/hatch3r-resilience-patterns.md +154 -0
  85. package/rules/hatch3r-resilience-patterns.mdc +150 -0
  86. package/rules/hatch3r-secrets-management.md +29 -0
  87. package/rules/hatch3r-secrets-management.mdc +29 -0
  88. package/rules/hatch3r-testing.md +139 -43
  89. package/rules/hatch3r-testing.mdc +139 -43
  90. package/rules/hatch3r-ux-states-and-flows.md +149 -0
  91. package/rules/hatch3r-ux-states-and-flows.mdc +145 -0
  92. package/skills/hatch3r-a11y-audit/SKILL.md +14 -0
  93. package/skills/hatch3r-ai-feature/SKILL.md +134 -0
  94. package/skills/hatch3r-api-spec/SKILL.md +5 -0
  95. package/skills/hatch3r-architecture-review/SKILL.md +14 -0
  96. package/skills/hatch3r-bug-fix/SKILL.md +5 -0
  97. package/skills/hatch3r-ci-pipeline/SKILL.md +14 -0
  98. package/skills/hatch3r-cli-aichat/SKILL.md +84 -0
  99. package/skills/hatch3r-cli-ast-grep/SKILL.md +85 -0
  100. package/skills/hatch3r-cli-az-devops/SKILL.md +89 -0
  101. package/skills/hatch3r-cli-bat/SKILL.md +85 -0
  102. package/skills/hatch3r-cli-comby/SKILL.md +85 -0
  103. package/skills/hatch3r-cli-csvkit/SKILL.md +84 -0
  104. package/skills/hatch3r-cli-delta/SKILL.md +86 -0
  105. package/skills/hatch3r-cli-difftastic/SKILL.md +84 -0
  106. package/skills/hatch3r-cli-docker/SKILL.md +89 -0
  107. package/skills/hatch3r-cli-duckdb/SKILL.md +84 -0
  108. package/skills/hatch3r-cli-fd/SKILL.md +85 -0
  109. package/skills/hatch3r-cli-fzf/SKILL.md +84 -0
  110. package/skills/hatch3r-cli-gh/SKILL.md +90 -0
  111. package/skills/hatch3r-cli-glab/SKILL.md +89 -0
  112. package/skills/hatch3r-cli-jq/SKILL.md +85 -0
  113. package/skills/hatch3r-cli-lazygit/SKILL.md +78 -0
  114. package/skills/hatch3r-cli-llm/SKILL.md +84 -0
  115. package/skills/hatch3r-cli-miller/SKILL.md +84 -0
  116. package/skills/hatch3r-cli-mods/SKILL.md +84 -0
  117. package/skills/hatch3r-cli-overview/SKILL.md +60 -0
  118. package/skills/hatch3r-cli-playwright/SKILL.md +89 -0
  119. package/skills/hatch3r-cli-podman/SKILL.md +84 -0
  120. package/skills/hatch3r-cli-ripgrep/SKILL.md +85 -0
  121. package/skills/hatch3r-cli-rtk/SKILL.md +91 -0
  122. package/skills/hatch3r-cli-sd/SKILL.md +85 -0
  123. package/skills/hatch3r-cli-stagehand/SKILL.md +79 -0
  124. package/skills/hatch3r-cli-taplo/SKILL.md +84 -0
  125. package/skills/hatch3r-cli-xsv/SKILL.md +89 -0
  126. package/skills/hatch3r-cli-yq/SKILL.md +85 -0
  127. package/skills/hatch3r-cli-zstd/SKILL.md +85 -0
  128. package/skills/hatch3r-context-health/SKILL.md +14 -0
  129. package/skills/hatch3r-cost-tracking/SKILL.md +14 -0
  130. package/skills/hatch3r-customize/SKILL.md +14 -0
  131. package/skills/hatch3r-dep-audit/SKILL.md +14 -0
  132. package/skills/hatch3r-design-system-detect/SKILL.md +162 -0
  133. package/skills/hatch3r-feature/SKILL.md +2 -0
  134. package/skills/hatch3r-gh-agentic-workflows/SKILL.md +13 -0
  135. package/skills/hatch3r-handoff-prepare/SKILL.md +160 -0
  136. package/skills/hatch3r-handoff-resume/SKILL.md +171 -0
  137. package/skills/hatch3r-incident-response/SKILL.md +14 -0
  138. package/skills/hatch3r-issue-workflow/SKILL.md +5 -0
  139. package/skills/hatch3r-logical-refactor/SKILL.md +14 -0
  140. package/skills/hatch3r-migration/SKILL.md +14 -0
  141. package/skills/hatch3r-observability-verify/SKILL.md +133 -0
  142. package/skills/hatch3r-perf-audit/SKILL.md +14 -0
  143. package/skills/hatch3r-pr-creation/SKILL.md +14 -0
  144. package/skills/hatch3r-qa-validation/SKILL.md +18 -0
  145. package/skills/hatch3r-recipe/SKILL.md +14 -0
  146. package/skills/hatch3r-refactor/SKILL.md +14 -0
  147. package/skills/hatch3r-release/SKILL.md +14 -0
  148. package/skills/hatch3r-reliability-verify/SKILL.md +144 -0
  149. package/skills/hatch3r-ui-ux-verify/SKILL.md +136 -0
  150. package/skills/hatch3r-visual-refactor/SKILL.md +15 -1
@@ -0,0 +1,170 @@
1
+ ---
2
+ id: hatch3r-auth-patterns
3
+ type: rule
4
+ description: Authentication and authorization patterns for end-user apps — OAuth 2.1, OIDC, DPoP, JWT rotation, cookie security, RBAC vs ABAC vs ReBAC rubric
5
+ scope: "**/auth/**,**/login/**,**/session/**,**/oauth/**,**/oidc/**,**/jwt/**,**/permissions/**,**/policies/**,**/middleware/**"
6
+ tags: [security, implementation]
7
+ quality_charter: agents/shared/quality-charter.md
8
+ cache_friendly: true
9
+ ---
10
+ # Authentication & Authorization Patterns
11
+
12
+ Backend-side identity stack for end-user apps. Pairs with `rules/hatch3r-passkey-server.md` (WebAuthn server ceremony) and the frontend rules `rules/hatch3r-ux-states-and-flows.md` + `rules/hatch3r-ai-ux-patterns.md` (identifier-first login, passkey Conditional UI).
13
+
14
+ ## OAuth 2.1 (Name It)
15
+
16
+ Adopt OAuth 2.1 (`draft-ietf-oauth-v2-1`, draft-15 Mar 2026) over OAuth 2.0. Reference RFC 9700 (OAuth Security BCP, Jan 2025) as the operative compliance bar.
17
+
18
+ - PKCE required on every public client (web SPA, mobile, desktop) AND every confidential client.
19
+ - Implicit grant REMOVED. Resource Owner Password Credentials (ROPC) grant REMOVED. Never use either.
20
+ - Exact redirect-URI string matching. No wildcards, no substring match, no prefix match.
21
+ - Refresh-token rotation with reuse detection: on detected reuse, revoke the entire refresh-token family and force re-authentication.
22
+ - Access-token TTL 5-15 min; refresh-token TTL bounded (8-72h sliding for SPAs, longer for native).
23
+ - Authorization Code grant + PKCE is the only public-client grant. Client Credentials for service-to-service.
24
+
25
+ ## OIDC ID-Token Validation
26
+
27
+ Every ID token received from an OIDC provider must validate ALL of the following before a session is created:
28
+
29
+ | Check | Rule |
30
+ |-------|------|
31
+ | `iss` | Equal to the expected issuer URL (string match) |
32
+ | `aud` | Contains this client's `client_id` |
33
+ | `azp` | Equals `client_id` when present and when `aud` has multiple values |
34
+ | `exp` | Now < `exp` |
35
+ | `iat` | `now - iat` within tolerable skew (default 5 min) |
36
+ | `auth_time` | Sanity-checked against session policy (max-age, prompt=login) |
37
+ | `nonce` | Equals the nonce generated for this authorization request (replay defense) |
38
+ | Signature | Verified against the issuer's JWKS; `kid` selects the current key |
39
+
40
+ Logout: implement BOTH RP-initiated logout (`end_session_endpoint` per OIDC RP-Initiated Logout 1.0) AND back-channel logout (server-to-server session-invalidation callback) for SSO sessions. ID-token-only state has no server invalidation path — pair with a server-side session record.
41
+
42
+ ## DPoP — Sender-Constrained Tokens (RFC 9449)
43
+
44
+ For browser-resident or public-client access tokens, bind tokens to a client-held key with DPoP. Replaces mTLS for clients that cannot manage certificates.
45
+
46
+ - Client generates an ECDSA or RSA keypair, stored non-extractable (WebCrypto `extractable: false`).
47
+ - Every protected request carries a `DPoP` header — a signed JWT with claims `htm` (HTTP method), `htu` (full URL), `iat`, `jti` (replay-cache key), and the public JWK in `jwk` header.
48
+ - Access token contains a `cnf.jkt` claim — SHA-256 JWK thumbprint of the bound key. Server verifies the DPoP-proof JWK thumbprint matches the access token's `cnf.jkt`.
49
+ - Server replay cache stores `jti` for the proof's `iat` window (default 60s skew + 5 min retention).
50
+ - Service-to-service: prefer mTLS (`x5t#S256` cnf claim) where the certificate chain is manageable; DPoP for browser/mobile.
51
+
52
+ ## JWT Pitfalls (RFC 8725 BCP)
53
+
54
+ - Reject `alg: none` always. Reject `alg: HS*` when the verification key is public (RS256/ES256 key-confusion attack).
55
+ - Pin the expected `alg` per issuer. Server config names the algorithm — never trust the `alg` header without an allowlist.
56
+ - JWKS endpoint cache TTL 1-24 hours. `kid` selects the current key. Rotation supported by publishing N+1 before retiring N (overlap window >= 2 * cache TTL).
57
+ - Audience binding mandatory. Each service has its own `aud` value and rejects tokens not minted for it.
58
+ - Revocation strategy: short access-TTL + periodic refresh OR introspection (RFC 7662) OR a revocation list for long-TTL tokens. Never assume tokens are revocable without one of these.
59
+ - No PII, no sensitive data in JWT payload. JWT payloads are base64-readable by anyone holding the token.
60
+
61
+ ## Cookie Security
62
+
63
+ Every auth-bearing cookie must set:
64
+
65
+ - `__Host-` prefix — implies `Path=/`, `Secure`, no `Domain` attribute. The prefix blocks subdomain shadowing.
66
+ - `HttpOnly` — blocks JS read.
67
+ - `Secure` — TLS-only transmission.
68
+ - `SameSite=Strict` for primary session cookies. Use `Lax` only when cross-site GET reads are required.
69
+ - `SameSite=None` REQUIRES `Partitioned` per CHIPS. Chrome's 2026 enforcement plan treats unpartitioned third-party cookies as deprecated.
70
+ - Short expiry (8-72h sliding); rolling refresh on activity.
71
+
72
+ CSRF defense ordering: `SameSite=Strict` is the primary defense for session cookies. Add a double-submit token (Origin/Cookie pair) for state-changing requests reachable from `SameSite=Lax` cookies. Validate `Origin` and `Sec-Fetch-Site` headers on high-value mutations.
73
+
74
+ ## MFA and NIST 800-63B-4 AAL Mapping
75
+
76
+ NIST SP 800-63B-4 (finalized mid-2025) demoted SMS to a restricted authenticator. Email OTP is deprecated. Map operations to AAL:
77
+
78
+ | Level | Authenticators | Use Case |
79
+ |-------|---------------|----------|
80
+ | AAL1 | Single factor — password OR WebAuthn UV | Low-risk reads, public-facing content |
81
+ | AAL2 | Two factor — password + TOTP, OR passkey (WebAuthn) with UV | Account access, settings changes |
82
+ | AAL3 | Hardware-bound multi-factor — WebAuthn UV with hardware-backed key | Admin actions, financial transfers, key rotation |
83
+
84
+ Step-up auth pattern: when a session is AAL1 and a sensitive op is requested (delete account, change email, change password, transfer funds, rotate API key, change billing), re-prompt the user for a fresh authentication. Issue a short-lived step-up token (5-15 min) carrying the AAL upgrade, scoped to the operation.
85
+
86
+ ## Authorization Model Rubric
87
+
88
+ Pick the model per app complexity. Document the choice in the project spec.
89
+
90
+ | Model | Use When | Engines |
91
+ |-------|----------|---------|
92
+ | **RBAC** (roles to permissions) | Flat-org tools, role count <20, permissions don't depend on resource attributes | App-layer; CASL; Pundit |
93
+ | **ABAC** (attributes to policy) | Access depends on user/resource attributes — department, region, classification, time-of-day | OPA (Rego), AWS Cedar |
94
+ | **ReBAC** (relationships to permissions) | Collaboration apps with sharing graphs — "user can edit doc if member of folder shared with team" | SpiceDB, OpenFGA, Permify, AuthZed |
95
+
96
+ ReBAC reference: Google Zanzibar paper (USENIX ATC 2019). For new collaboration apps, default to ReBAC over hand-rolled per-resource ACL tables.
97
+
98
+ **AuthZEN Authorization API 1.0** (OIDF Final, Jan 2026) — engine-neutral PEP-to-PDP wire format. Adopt for service architectures where authorization is centralized.
99
+
100
+ ## Multi-Tenancy Isolation
101
+
102
+ - Every tenant-scoped table carries a `tenant_id` column.
103
+ - Postgres Row-Level Security policies enforce isolation at the DB layer: `CREATE POLICY tenant_isolation ON {table} USING (tenant_id = current_setting('app.tenant_id')::uuid)`.
104
+ - Per-tenant signing keys for sensitive crypto operations (BYOK pattern for Level 4 data per `rules/hatch3r-data-classification.md`).
105
+ - Cross-tenant access attempts return 404, not 403 — never confirm tenant existence to unauthorized callers.
106
+ - Integration tests assert cross-tenant access returns 404 on every tenant-scoped endpoint.
107
+
108
+ ## Token Storage on Client
109
+
110
+ - Web: never `localStorage` or `sessionStorage` for tokens. Use `HttpOnly` `__Host-` cookies for sessions, OR in-memory access token + `HttpOnly` refresh cookie (BFF / silent-refresh pattern).
111
+ - Mobile iOS: Keychain Services with `kSecAttrAccessibleWhenUnlockedThisDeviceOnly`.
112
+ - Mobile Android: EncryptedSharedPreferences backed by Android Keystore.
113
+ - Never log full tokens. Log the `jti` (token ID) only for audit correlation.
114
+
115
+ ## Secret Rotation Cadence
116
+
117
+ - Automated via HashiCorp Vault / AWS Secrets Manager / GCP Secret Manager — never manual.
118
+ - Rotation cadence per secret type — see `rules/hatch3r-secrets-management.md`.
119
+ - Zero-downtime rotation pattern: publish N+1, wait >= 2 * cache TTL, switch signing to N+1, retire N after refresh-token max-age.
120
+
121
+ ## Auth Provider 2026 Landscape — Roll vs Buy
122
+
123
+ Decision rubric: managed for B2B + SSO/SAML/SCIM requirements; self-host when compliance forbids third-party identity OR when cost crosses break-even at scale.
124
+
125
+ | Provider | Sweet Spot |
126
+ |----------|-----------|
127
+ | Clerk | Best DX for React/Next.js consumer apps |
128
+ | Supabase Auth | Postgres-native + RLS-integrated stacks |
129
+ | WorkOS | Enterprise SSO + SCIM + Directory Sync |
130
+ | Auth0 / Okta | Enterprise B2B with mature compliance |
131
+ | Stytch | Passwordless + WebAuthn focus |
132
+ | Better Auth | OSS framework-agnostic, full control |
133
+ | Auth.js (NextAuth.js) | Next.js with minimal external dependency |
134
+ | FusionAuth / Keycloak / Ory | Self-host with full IdP capability |
135
+
136
+ ## API Key Design
137
+
138
+ - Prefix convention for secret-scanner detection (`sk_live_*`, `pk_live_*`).
139
+ - Hash-only storage server-side (Argon2id or SHA-256 with per-key salt); never store plaintext.
140
+ - Per-key scope grants (resource + method allowlist).
141
+ - Per-key rate limit; per-key usage analytics with last-used timestamp.
142
+ - Revocation API; rotate quarterly; never log the full key value.
143
+ - For human users, replace API keys with passkeys + short-lived tokens.
144
+
145
+ ## Audit Logging for Auth Events
146
+
147
+ Every auth event logged with `actor` (user_id), `target` (resource_id), `ip`, `user_agent`, `result` (success/failure/code), `timestamp`, and `trace_id` for SIEM correlation. Tamper-resistant append-only store; 1-year retention minimum.
148
+
149
+ Required event set: login success, login failure, MFA challenge issued, MFA verified, MFA failed, password reset requested, password reset completed, email change, role/scope grant, role/scope revoke, token issued, token revoked, session terminated, passkey added, passkey removed, step-up auth challenge, step-up auth verified.
150
+
151
+ ## Cross-References
152
+
153
+ - `rules/hatch3r-passkey-server.md` — server-side WebAuthn ceremony (paired companion).
154
+ - `rules/hatch3r-ux-states-and-flows.md` — frontend identifier-first login + Conditional UI.
155
+ - `rules/hatch3r-ai-ux-patterns.md` — frontend WebAuthn UX patterns.
156
+ - `rules/hatch3r-api-versioning.md` — OAuth 2.1 in the API-versioning context.
157
+ - `rules/hatch3r-secrets-management.md` — JWT signing key + OAuth client secret rotation cadence.
158
+ - `rules/hatch3r-data-classification.md` — multi-tenant data isolation + BYOK.
159
+
160
+ ## References
161
+
162
+ - RFC 9700 — OAuth 2.0 Security Best Current Practice (Jan 2025).
163
+ - RFC 9449 — OAuth 2.0 Demonstrating Proof of Possession (DPoP).
164
+ - RFC 8725 — JSON Web Token Best Current Practice.
165
+ - `draft-ietf-oauth-v2-1` — The OAuth 2.1 Authorization Framework.
166
+ - OpenID Connect Core 1.0 + RP-Initiated Logout 1.0 + Back-Channel Logout 1.0.
167
+ - NIST SP 800-63B-4 — Digital Identity Guidelines: Authentication and Authenticator Management.
168
+ - FAPI 2.0 Final (Feb 2025) — Financial-grade API profiles.
169
+ - AuthZEN Authorization API 1.0 Final (OpenID Foundation, Jan 2026).
170
+ - Google Zanzibar — Consistent, Global Authorization (USENIX ATC 2019).
@@ -0,0 +1,166 @@
1
+ ---
2
+ description: Authentication and authorization patterns for end-user apps — OAuth 2.1, OIDC, DPoP, JWT rotation, cookie security, RBAC vs ABAC vs ReBAC rubric
3
+ globs: ["**/auth/**", "**/login/**", "**/session/**", "**/oauth/**", "**/oidc/**", "**/jwt/**", "**/permissions/**", "**/policies/**", "**/middleware/**"]
4
+ alwaysApply: false
5
+ ---
6
+ # Authentication & Authorization Patterns
7
+
8
+ Backend-side identity stack for end-user apps. Pairs with `rules/hatch3r-passkey-server.md` (WebAuthn server ceremony) and the frontend rules `rules/hatch3r-ux-states-and-flows.md` + `rules/hatch3r-ai-ux-patterns.md` (identifier-first login, passkey Conditional UI).
9
+
10
+ ## OAuth 2.1 (Name It)
11
+
12
+ Adopt OAuth 2.1 (`draft-ietf-oauth-v2-1`, draft-15 Mar 2026) over OAuth 2.0. Reference RFC 9700 (OAuth Security BCP, Jan 2025) as the operative compliance bar.
13
+
14
+ - PKCE required on every public client (web SPA, mobile, desktop) AND every confidential client.
15
+ - Implicit grant REMOVED. Resource Owner Password Credentials (ROPC) grant REMOVED. Never use either.
16
+ - Exact redirect-URI string matching. No wildcards, no substring match, no prefix match.
17
+ - Refresh-token rotation with reuse detection: on detected reuse, revoke the entire refresh-token family and force re-authentication.
18
+ - Access-token TTL 5-15 min; refresh-token TTL bounded (8-72h sliding for SPAs, longer for native).
19
+ - Authorization Code grant + PKCE is the only public-client grant. Client Credentials for service-to-service.
20
+
21
+ ## OIDC ID-Token Validation
22
+
23
+ Every ID token received from an OIDC provider must validate ALL of the following before a session is created:
24
+
25
+ | Check | Rule |
26
+ |-------|------|
27
+ | `iss` | Equal to the expected issuer URL (string match) |
28
+ | `aud` | Contains this client's `client_id` |
29
+ | `azp` | Equals `client_id` when present and when `aud` has multiple values |
30
+ | `exp` | Now < `exp` |
31
+ | `iat` | `now - iat` within tolerable skew (default 5 min) |
32
+ | `auth_time` | Sanity-checked against session policy (max-age, prompt=login) |
33
+ | `nonce` | Equals the nonce generated for this authorization request (replay defense) |
34
+ | Signature | Verified against the issuer's JWKS; `kid` selects the current key |
35
+
36
+ Logout: implement BOTH RP-initiated logout (`end_session_endpoint` per OIDC RP-Initiated Logout 1.0) AND back-channel logout (server-to-server session-invalidation callback) for SSO sessions. ID-token-only state has no server invalidation path — pair with a server-side session record.
37
+
38
+ ## DPoP — Sender-Constrained Tokens (RFC 9449)
39
+
40
+ For browser-resident or public-client access tokens, bind tokens to a client-held key with DPoP. Replaces mTLS for clients that cannot manage certificates.
41
+
42
+ - Client generates an ECDSA or RSA keypair, stored non-extractable (WebCrypto `extractable: false`).
43
+ - Every protected request carries a `DPoP` header — a signed JWT with claims `htm` (HTTP method), `htu` (full URL), `iat`, `jti` (replay-cache key), and the public JWK in `jwk` header.
44
+ - Access token contains a `cnf.jkt` claim — SHA-256 JWK thumbprint of the bound key. Server verifies the DPoP-proof JWK thumbprint matches the access token's `cnf.jkt`.
45
+ - Server replay cache stores `jti` for the proof's `iat` window (default 60s skew + 5 min retention).
46
+ - Service-to-service: prefer mTLS (`x5t#S256` cnf claim) where the certificate chain is manageable; DPoP for browser/mobile.
47
+
48
+ ## JWT Pitfalls (RFC 8725 BCP)
49
+
50
+ - Reject `alg: none` always. Reject `alg: HS*` when the verification key is public (RS256/ES256 key-confusion attack).
51
+ - Pin the expected `alg` per issuer. Server config names the algorithm — never trust the `alg` header without an allowlist.
52
+ - JWKS endpoint cache TTL 1-24 hours. `kid` selects the current key. Rotation supported by publishing N+1 before retiring N (overlap window >= 2 * cache TTL).
53
+ - Audience binding mandatory. Each service has its own `aud` value and rejects tokens not minted for it.
54
+ - Revocation strategy: short access-TTL + periodic refresh OR introspection (RFC 7662) OR a revocation list for long-TTL tokens. Never assume tokens are revocable without one of these.
55
+ - No PII, no sensitive data in JWT payload. JWT payloads are base64-readable by anyone holding the token.
56
+
57
+ ## Cookie Security
58
+
59
+ Every auth-bearing cookie must set:
60
+
61
+ - `__Host-` prefix — implies `Path=/`, `Secure`, no `Domain` attribute. The prefix blocks subdomain shadowing.
62
+ - `HttpOnly` — blocks JS read.
63
+ - `Secure` — TLS-only transmission.
64
+ - `SameSite=Strict` for primary session cookies. Use `Lax` only when cross-site GET reads are required.
65
+ - `SameSite=None` REQUIRES `Partitioned` per CHIPS. Chrome's 2026 enforcement plan treats unpartitioned third-party cookies as deprecated.
66
+ - Short expiry (8-72h sliding); rolling refresh on activity.
67
+
68
+ CSRF defense ordering: `SameSite=Strict` is the primary defense for session cookies. Add a double-submit token (Origin/Cookie pair) for state-changing requests reachable from `SameSite=Lax` cookies. Validate `Origin` and `Sec-Fetch-Site` headers on high-value mutations.
69
+
70
+ ## MFA and NIST 800-63B-4 AAL Mapping
71
+
72
+ NIST SP 800-63B-4 (finalized mid-2025) demoted SMS to a restricted authenticator. Email OTP is deprecated. Map operations to AAL:
73
+
74
+ | Level | Authenticators | Use Case |
75
+ |-------|---------------|----------|
76
+ | AAL1 | Single factor — password OR WebAuthn UV | Low-risk reads, public-facing content |
77
+ | AAL2 | Two factor — password + TOTP, OR passkey (WebAuthn) with UV | Account access, settings changes |
78
+ | AAL3 | Hardware-bound multi-factor — WebAuthn UV with hardware-backed key | Admin actions, financial transfers, key rotation |
79
+
80
+ Step-up auth pattern: when a session is AAL1 and a sensitive op is requested (delete account, change email, change password, transfer funds, rotate API key, change billing), re-prompt the user for a fresh authentication. Issue a short-lived step-up token (5-15 min) carrying the AAL upgrade, scoped to the operation.
81
+
82
+ ## Authorization Model Rubric
83
+
84
+ Pick the model per app complexity. Document the choice in the project spec.
85
+
86
+ | Model | Use When | Engines |
87
+ |-------|----------|---------|
88
+ | **RBAC** (roles to permissions) | Flat-org tools, role count <20, permissions don't depend on resource attributes | App-layer; CASL; Pundit |
89
+ | **ABAC** (attributes to policy) | Access depends on user/resource attributes — department, region, classification, time-of-day | OPA (Rego), AWS Cedar |
90
+ | **ReBAC** (relationships to permissions) | Collaboration apps with sharing graphs — "user can edit doc if member of folder shared with team" | SpiceDB, OpenFGA, Permify, AuthZed |
91
+
92
+ ReBAC reference: Google Zanzibar paper (USENIX ATC 2019). For new collaboration apps, default to ReBAC over hand-rolled per-resource ACL tables.
93
+
94
+ **AuthZEN Authorization API 1.0** (OIDF Final, Jan 2026) — engine-neutral PEP-to-PDP wire format. Adopt for service architectures where authorization is centralized.
95
+
96
+ ## Multi-Tenancy Isolation
97
+
98
+ - Every tenant-scoped table carries a `tenant_id` column.
99
+ - Postgres Row-Level Security policies enforce isolation at the DB layer: `CREATE POLICY tenant_isolation ON {table} USING (tenant_id = current_setting('app.tenant_id')::uuid)`.
100
+ - Per-tenant signing keys for sensitive crypto operations (BYOK pattern for Level 4 data per `rules/hatch3r-data-classification.md`).
101
+ - Cross-tenant access attempts return 404, not 403 — never confirm tenant existence to unauthorized callers.
102
+ - Integration tests assert cross-tenant access returns 404 on every tenant-scoped endpoint.
103
+
104
+ ## Token Storage on Client
105
+
106
+ - Web: never `localStorage` or `sessionStorage` for tokens. Use `HttpOnly` `__Host-` cookies for sessions, OR in-memory access token + `HttpOnly` refresh cookie (BFF / silent-refresh pattern).
107
+ - Mobile iOS: Keychain Services with `kSecAttrAccessibleWhenUnlockedThisDeviceOnly`.
108
+ - Mobile Android: EncryptedSharedPreferences backed by Android Keystore.
109
+ - Never log full tokens. Log the `jti` (token ID) only for audit correlation.
110
+
111
+ ## Secret Rotation Cadence
112
+
113
+ - Automated via HashiCorp Vault / AWS Secrets Manager / GCP Secret Manager — never manual.
114
+ - Rotation cadence per secret type — see `rules/hatch3r-secrets-management.md`.
115
+ - Zero-downtime rotation pattern: publish N+1, wait >= 2 * cache TTL, switch signing to N+1, retire N after refresh-token max-age.
116
+
117
+ ## Auth Provider 2026 Landscape — Roll vs Buy
118
+
119
+ Decision rubric: managed for B2B + SSO/SAML/SCIM requirements; self-host when compliance forbids third-party identity OR when cost crosses break-even at scale.
120
+
121
+ | Provider | Sweet Spot |
122
+ |----------|-----------|
123
+ | Clerk | Best DX for React/Next.js consumer apps |
124
+ | Supabase Auth | Postgres-native + RLS-integrated stacks |
125
+ | WorkOS | Enterprise SSO + SCIM + Directory Sync |
126
+ | Auth0 / Okta | Enterprise B2B with mature compliance |
127
+ | Stytch | Passwordless + WebAuthn focus |
128
+ | Better Auth | OSS framework-agnostic, full control |
129
+ | Auth.js (NextAuth.js) | Next.js with minimal external dependency |
130
+ | FusionAuth / Keycloak / Ory | Self-host with full IdP capability |
131
+
132
+ ## API Key Design
133
+
134
+ - Prefix convention for secret-scanner detection (`sk_live_*`, `pk_live_*`).
135
+ - Hash-only storage server-side (Argon2id or SHA-256 with per-key salt); never store plaintext.
136
+ - Per-key scope grants (resource + method allowlist).
137
+ - Per-key rate limit; per-key usage analytics with last-used timestamp.
138
+ - Revocation API; rotate quarterly; never log the full key value.
139
+ - For human users, replace API keys with passkeys + short-lived tokens.
140
+
141
+ ## Audit Logging for Auth Events
142
+
143
+ Every auth event logged with `actor` (user_id), `target` (resource_id), `ip`, `user_agent`, `result` (success/failure/code), `timestamp`, and `trace_id` for SIEM correlation. Tamper-resistant append-only store; 1-year retention minimum.
144
+
145
+ Required event set: login success, login failure, MFA challenge issued, MFA verified, MFA failed, password reset requested, password reset completed, email change, role/scope grant, role/scope revoke, token issued, token revoked, session terminated, passkey added, passkey removed, step-up auth challenge, step-up auth verified.
146
+
147
+ ## Cross-References
148
+
149
+ - `rules/hatch3r-passkey-server.md` — server-side WebAuthn ceremony (paired companion).
150
+ - `rules/hatch3r-ux-states-and-flows.md` — frontend identifier-first login + Conditional UI.
151
+ - `rules/hatch3r-ai-ux-patterns.md` — frontend WebAuthn UX patterns.
152
+ - `rules/hatch3r-api-versioning.md` — OAuth 2.1 in the API-versioning context.
153
+ - `rules/hatch3r-secrets-management.md` — JWT signing key + OAuth client secret rotation cadence.
154
+ - `rules/hatch3r-data-classification.md` — multi-tenant data isolation + BYOK.
155
+
156
+ ## References
157
+
158
+ - RFC 9700 — OAuth 2.0 Security Best Current Practice (Jan 2025).
159
+ - RFC 9449 — OAuth 2.0 Demonstrating Proof of Possession (DPoP).
160
+ - RFC 8725 — JSON Web Token Best Current Practice.
161
+ - `draft-ietf-oauth-v2-1` — The OAuth 2.1 Authorization Framework.
162
+ - OpenID Connect Core 1.0 + RP-Initiated Logout 1.0 + Back-Channel Logout 1.0.
163
+ - NIST SP 800-63B-4 — Digital Identity Guidelines: Authentication and Authenticator Management.
164
+ - FAPI 2.0 Final (Feb 2025) — Financial-grade API profiles.
165
+ - AuthZEN Authorization API 1.0 Final (OpenID Foundation, Jan 2026).
166
+ - Google Zanzibar — Consistent, Global Authorization (USENIX ATC 2019).
@@ -10,6 +10,15 @@ cache_friendly: true
10
10
  ---
11
11
  # Component Conventions
12
12
 
13
+ ## Library and Token Detection (Mandatory Pre-Author Step)
14
+
15
+ Before authoring any new UI primitive, complete this scan and reuse > extend > create:
16
+
17
+ - Scan `package.json` for `@radix-ui/*`, shadcn (`components.json`), Tailwind v4, MUI, or Chakra. If a matching primitive exists in those libraries, extend it instead of writing a new one.
18
+ - Locate the token source: `tokens.json` (DTCG spec, 2025.10 revision), `src/styles/tokens.css`, Tailwind `@theme` block (v4), or `tailwind.config.{js,ts}` (v3 fallback). Reference the token by name — never hardcode the resolved value.
19
+ - Map the component library convention before writing files: shadcn projects use `src/components/ui/*`; non-shadcn projects typically use `src/components/primitives/*`. Place new files in the existing directory layout.
20
+ - Cross-reference `rules/hatch3r-design-system-detection.md` for the full detection workflow and tooling.
21
+
13
22
  ## Structure
14
23
 
15
24
  - Use framework-recommended component syntax (e.g., `<script setup>` for Vue).
@@ -41,6 +50,20 @@ cache_friendly: true
41
50
 
42
51
  ## State Patterns (Required)
43
52
 
53
+ ### Four-State Surface Contract
54
+
55
+ Every async view must render all four states. A missing state is a blocker for merge.
56
+
57
+ - **Loading:** skeleton with explicit `width` and `height` matching the final content dimensions to prevent Cumulative Layout Shift (CLS). Generic spinners on content surfaces are insufficient.
58
+ - **Empty:** distinguish three sub-types, each with the matching CTA:
59
+ - Cold-start (no data ever) — onboarding CTA (e.g., "Create your first project").
60
+ - Active-filter (filters/search exclude all data) — clear-filters CTA.
61
+ - No-permission (auth scope blocks access) — request-access CTA.
62
+ - **Error:** show the cause, a retry action, and a fallback path; use a corrective verb ("Try again", "Reload"). Never use "Oops" or generic copy that hides the cause.
63
+ - **Partial:** when some data resolves and some fails, render a banner explaining the gap plus the degraded data plus a retry control for the failed slice.
64
+
65
+ Cross-reference `rules/hatch3r-ux-states-and-flows.md` for the full state-flow specification.
66
+
44
67
  ### Loading States
45
68
  - Use skeleton screens (not spinners) for content areas — match the layout shape of the loaded content.
46
69
  - Apply a shimmer/pulse CSS animation on skeletons to indicate activity.
@@ -88,6 +111,13 @@ cache_friendly: true
88
111
  - Provide clear success feedback: redirect to the result page or display a success toast.
89
112
  - Prevent double submission by disabling the button and ignoring duplicate submit events during pending requests.
90
113
 
114
+ ### Error Recovery
115
+ - Clear inline field errors immediately when the user enters a corrective character — no debounce on the clear path.
116
+ - Re-enable the submit button in real time as the form returns to a valid state.
117
+ - On submit with errors, render an error summary at the top of the form with anchor links to each invalid field; move focus to the summary container, not to the first invalid field.
118
+ - Required attributes on inputs: `autocomplete` (HTML autofill tokens), `inputmode` (matches expected character set), `aria-describedby` (links help/format hints), and `aria-invalid="true"` once invalid.
119
+ - Never use a disabled submit button as the only error signal — disabled state is unreadable to many screen readers and gives no recovery path.
120
+
91
121
  ### Accessible Labels
92
122
  - Every `<input>`, `<select>`, and `<textarea>` must have a visible `<label>` element with a matching `for`/`id` pair.
93
123
  - Mark required fields with a visual asterisk (`*`) and screen-reader-only text ("required").
@@ -5,6 +5,15 @@ alwaysApply: false
5
5
  ---
6
6
  # Component Conventions
7
7
 
8
+ ## Library and Token Detection (Mandatory Pre-Author Step)
9
+
10
+ Before authoring any new UI primitive, complete this scan and reuse > extend > create:
11
+
12
+ - Scan `package.json` for `@radix-ui/*`, shadcn (`components.json`), Tailwind v4, MUI, or Chakra. If a matching primitive exists in those libraries, extend it instead of writing a new one.
13
+ - Locate the token source: `tokens.json` (DTCG spec, 2025.10 revision), `src/styles/tokens.css`, Tailwind `@theme` block (v4), or `tailwind.config.{js,ts}` (v3 fallback). Reference the token by name — never hardcode the resolved value.
14
+ - Map the component library convention before writing files: shadcn projects use `src/components/ui/*`; non-shadcn projects typically use `src/components/primitives/*`. Place new files in the existing directory layout.
15
+ - Cross-reference `rules/hatch3r-design-system-detection.md` for the full detection workflow and tooling.
16
+
8
17
  ## Structure
9
18
 
10
19
  - Use framework-recommended component syntax (e.g., `<script setup>` for Vue).
@@ -36,6 +45,20 @@ alwaysApply: false
36
45
 
37
46
  ## State Patterns (Required)
38
47
 
48
+ ### Four-State Surface Contract
49
+
50
+ Every async view must render all four states. A missing state is a blocker for merge.
51
+
52
+ - **Loading:** skeleton with explicit `width` and `height` matching the final content dimensions to prevent Cumulative Layout Shift (CLS). Generic spinners on content surfaces are insufficient.
53
+ - **Empty:** distinguish three sub-types, each with the matching CTA:
54
+ - Cold-start (no data ever) — onboarding CTA (e.g., "Create your first project").
55
+ - Active-filter (filters/search exclude all data) — clear-filters CTA.
56
+ - No-permission (auth scope blocks access) — request-access CTA.
57
+ - **Error:** show the cause, a retry action, and a fallback path; use a corrective verb ("Try again", "Reload"). Never use "Oops" or generic copy that hides the cause.
58
+ - **Partial:** when some data resolves and some fails, render a banner explaining the gap plus the degraded data plus a retry control for the failed slice.
59
+
60
+ Cross-reference `rules/hatch3r-ux-states-and-flows.md` for the full state-flow specification.
61
+
39
62
  ### Loading States
40
63
  - Use skeleton screens (not spinners) for content areas — match the layout shape of the loaded content.
41
64
  - Apply a shimmer/pulse CSS animation on skeletons to indicate activity.
@@ -83,6 +106,13 @@ alwaysApply: false
83
106
  - Provide clear success feedback: redirect to the result page or display a success toast.
84
107
  - Prevent double submission by disabling the button and ignoring duplicate submit events during pending requests.
85
108
 
109
+ ### Error Recovery
110
+ - Clear inline field errors immediately when the user enters a corrective character — no debounce on the clear path.
111
+ - Re-enable the submit button in real time as the form returns to a valid state.
112
+ - On submit with errors, render an error summary at the top of the form with anchor links to each invalid field; move focus to the summary container, not to the first invalid field.
113
+ - Required attributes on inputs: `autocomplete` (HTML autofill tokens), `inputmode` (matches expected character set), `aria-describedby` (links help/format hints), and `aria-invalid="true"` once invalid.
114
+ - Never use a disabled submit button as the only error signal — disabled state is unreadable to many screen readers and gives no recovery path.
115
+
86
116
  ### Accessible Labels
87
117
  - Every `<input>`, `<select>`, and `<textarea>` must have a visible `<label>` element with a matching `for`/`id` pair.
88
118
  - Mark required fields with a visual asterisk (`*`) and screen-reader-only text ("required").
@@ -0,0 +1,131 @@
1
+ ---
2
+ id: hatch3r-container-hardening
3
+ type: rule
4
+ description: Container image hardening — digest pinning, distroless / Wolfi base, non-root user, SBOM-in-image, cosign signing + verification, multi-stage builds, CVE scanning
5
+ scope: "**/Dockerfile*,**/docker-compose*,**/*.containerfile,**/charts/**,**/k8s/**,**/kubernetes/**,**/manifests/**"
6
+ tags: [security, devops]
7
+ quality_charter: agents/shared/quality-charter.md
8
+ cache_friendly: true
9
+ ---
10
+ # Container Hardening
11
+
12
+ ## Base Image: Wolfi / Chainguard Images
13
+
14
+ The 2026 baseline for container images is Wolfi-OS via Chainguard Images — rebuilt nightly from source, granular per-package versions, no kernel, distroless philosophy. Distroless (Google) remains a valid fallback when Chainguard's commercial offering is out of scope.
15
+
16
+ - Pin every base image by digest, never by tag. Mutable tags (`latest`, `1`, `1.2`) are an attack vector — the registry can serve a different image under the same tag at any time.
17
+ - Example: `FROM cgr.dev/chainguard/node:latest@sha256:<64-hex-digest>` (the `latest` tag is acceptable only when paired with a `@sha256:` digest pin; the digest is the authority).
18
+ - Drift detection: a scheduled CI job re-resolves base-image tags and opens a PR when a newer digest publishes; reviewer inspects CVE delta before merging.
19
+
20
+ ## Multi-Stage Builds
21
+
22
+ Separate the builder from the runtime image. The builder carries the full toolchain (compilers, package managers, dev headers); the runtime carries only the produced artifact plus a distroless or Wolfi base.
23
+
24
+ - Builder stage: install build deps, compile, run tests. May be heavy.
25
+ - Runtime stage: `FROM cgr.dev/chainguard/static:latest@sha256:...` (for static binaries) or `cgr.dev/chainguard/node:latest@sha256:...` (for Node services). `COPY --from=builder` only the artifacts needed at runtime.
26
+ - Result: smaller image, fewer CVEs at runtime, no source code or build tools shipped to production.
27
+
28
+ ## Non-Root User
29
+
30
+ Production containers run as a non-root user. Root-in-container plus container-escape-CVE equals root-on-host.
31
+
32
+ - `USER 65532:65532` (the `nobody` UID on most distros) or a named non-root user declared in the Dockerfile.
33
+ - Kubernetes pod security: `runAsNonRoot: true`, `runAsUser: 65532`, `runAsGroup: 65532`, `readOnlyRootFilesystem: true`, `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`.
34
+ - Writable paths use `emptyDir` or `persistentVolumeClaim` mounts, not the root filesystem.
35
+
36
+ ## No Shell, Minimal Binaries
37
+
38
+ Distroless `:nonroot` variants and Chainguard `static` images ship without `/bin/sh`. A compromised process cannot fall back to a shell for lateral movement.
39
+
40
+ - Production image set is `:nonroot` or `static`. Debug variants (`:debug`, `:debug-nonroot`) include `sh` and `busybox` and are pulled only for local troubleshooting.
41
+ - `kubectl debug --image=cgr.dev/chainguard/wolfi-base` provides ephemeral debug containers without baking shells into production images.
42
+
43
+ ## SBOM-in-Image
44
+
45
+ Every image carries a CycloneDX 1.6 SBOM, generated at build time and either embedded in the image or attached as an OCI artifact in the registry.
46
+
47
+ - Generation: `syft <image> -o cyclonedx-json` or BuildKit `--attest type=sbom`. Chainguard Images already ship with attached SBOMs.
48
+ - Attachment: `cosign attach sbom --sbom sbom.cdx.json <image>:<tag>` or BuildKit attestation in the OCI manifest.
49
+ - Deploy-time consumers fetch the SBOM via `cosign download sbom <image>` and match against the CVE feed before admission.
50
+
51
+ ## Image Signing — cosign
52
+
53
+ Every image is signed with cosign keyless mode via OIDC. Sigstore Fulcio issues a short-lived signing certificate scoped to the workflow identity; Rekor records the signature for tamper-evident audit.
54
+
55
+ - Sign in CI: `cosign sign --yes <registry>/<image>@<digest>`. Workflow grants `id-token: write` permission; no long-lived signing key.
56
+ - Verify at deploy: `cosign verify <image> --certificate-identity-regexp 'https://github\.com/org/repo/\.github/workflows/.*' --certificate-oidc-issuer https://token.actions.githubusercontent.com`.
57
+ - Admission enforcement: Sigstore Policy Controller (native admission with CUE or Rego), Kyverno (`verifyImages` rule), or OPA Gatekeeper + Ratify. Unsigned images rejected at admission, not just warned.
58
+
59
+ ## CVE Scanning in CI
60
+
61
+ Two scanners are run per image build: `trivy` for breadth (Wolfi advisory database, OS+language deps) and `grype` for Chainguard parity. Release is blocked on unpatched Critical or High CVEs without a documented suppression record.
62
+
63
+ - `trivy image --severity HIGH,CRITICAL --exit-code 1 <image>:<tag>` fails the job on any High/Critical.
64
+ - Periodic re-scan: a nightly job re-pulls each production image digest and rescans — newly-disclosed CVEs in already-deployed images surface here.
65
+ - Suppressions documented in `.trivyignore` with CVE ID, justification, expiry date, and owner. Expired suppressions fail the build.
66
+
67
+ ## Digest Pinning Everywhere
68
+
69
+ The same digest-not-tag rule extends beyond `FROM` lines to every place the image is referenced.
70
+
71
+ - Kubernetes manifests: `image: <registry>/<image>@sha256:<digest>` in Deployment, StatefulSet, Job, CronJob.
72
+ - Helm charts: `appVersion` references the digest; `image.tag` is the digest, not a semver tag.
73
+ - GitOps repos (Argo CD, Flux): the source of truth is the digest; image-update controllers (`flux image-update`) bump the digest on signed-image admission events.
74
+ - Pull policy: `imagePullPolicy: IfNotPresent` (digests are immutable so pull-once is safe); `Always` is only required when tags are used.
75
+
76
+ ## Reproducible Builds
77
+
78
+ Build inputs are pinned so the same `git checkout` produces the same image digest.
79
+
80
+ - `# syntax=docker/dockerfile:1.<minor>.<patch>` — pin to a specific BuildKit syntax version.
81
+ - Package installs pin versions: `apk add --no-cache nodejs=20.11.1-r0` (Wolfi/Alpine), `apt-get install -y nodejs=20.11.1*` (Debian).
82
+ - Deterministic `COPY` order: copy lockfile and install deps before copying source, so layer caching is stable.
83
+ - `SOURCE_DATE_EPOCH` set from git commit timestamp strips filesystem timestamps.
84
+ - Verify with `reproducible-containers/repro-build`: rebuild and compare digests; mismatches fail.
85
+
86
+ ## Secrets Handling in Images
87
+
88
+ Secrets never enter the image at build time. Runtime injection only.
89
+
90
+ - Forbidden: `COPY .env`, `ARG NPM_TOKEN`, `ENV API_KEY=...`. Build args persist in image history and are recoverable by anyone with image pull access.
91
+ - Build-time secrets (private registry tokens, SSH keys) use BuildKit `--mount=type=secret,id=<name>` — mounted at build, never persisted.
92
+ - Runtime secrets injected via container env (from Kubernetes Secret or vault sidecar), mounted file (CSI Secret Store driver), or IAM role / Workload Identity for cloud auth.
93
+
94
+ ## Health Checks
95
+
96
+ Every long-running container declares readiness, liveness, and startup probes. Cross-reference `rules/hatch3r-operability.md`.
97
+
98
+ - Dockerfile `HEALTHCHECK CMD <command>` for non-orchestrated deployments.
99
+ - Kubernetes `livenessProbe`, `readinessProbe`, `startupProbe` with HTTP, TCP, or exec checks. Startup probe allows slow boots (e.g., JVM warmup) without failing liveness during startup.
100
+ - Probe endpoints implemented at the application layer; `/healthz` (liveness), `/readyz` (readiness), `/startz` (startup) is the conventional split.
101
+
102
+ ## Image Size Budget
103
+
104
+ Runtime image targets under 200 MB compressed. Builds exceeding 500 MB compressed page the platform team for review.
105
+
106
+ - Strip debug symbols and source maps from production artifacts in the builder stage.
107
+ - Single-binary services (Go, Rust) target Chainguard `static` images — typical runtime under 20 MB.
108
+ - Multi-arch images do not multiply the size budget — each architecture is measured independently.
109
+
110
+ ## Verification Gate at Release
111
+
112
+ Every release pipeline executes the following gates before publish, all green:
113
+
114
+ - `cosign verify` against the workflow OIDC identity.
115
+ - `trivy image` and `grype` zero Critical, zero High (or all High suppressed with documented expiry).
116
+ - Image digest pinned in every consuming manifest (rejected if any `image:` line uses a tag without digest).
117
+ - Pod spec runs as non-root (`runAsNonRoot: true`), read-only root filesystem, dropped capabilities.
118
+ - SBOM attached and downloadable via `cosign download sbom`.
119
+
120
+ Cross-reference `agents/hatch3r-security-auditor.md` for runtime security audit; `agents/hatch3r-devops.md` for delivery integration; `rules/hatch3r-secrets-management.md` for OIDC trust-policy conditions; `rules/hatch3r-dependency-management.md` for SBOM tooling and SLSA provenance.
121
+
122
+ ## References
123
+
124
+ - Chainguard Images: https://edu.chainguard.dev/chainguard/chainguard-images/overview/
125
+ - Distroless: https://github.com/GoogleContainerTools/distroless
126
+ - Sigstore cosign: https://docs.sigstore.dev/cosign/overview/
127
+ - Sigstore Policy Controller: https://docs.sigstore.dev/policy-controller/overview/
128
+ - Kyverno image verification: https://kyverno.io/docs/policy-types/verify-images/sigstore/
129
+ - SLSA v1.0 spec: https://slsa.dev/spec/v1.0/
130
+ - Trivy: https://trivy.dev/latest/docs/target/container_image/
131
+ - CISA tj-actions advisory (CVE-2025-30066): https://www.cisa.gov/news-events/alerts/2025/03/18/supply-chain-compromise-third-party-github-action