FF Service · Phase 2b+ (Debug) Local/dev hardening surface · verification modes · persistence notes · cache-invalidation shape · policy-aware gating

Scaffold · local/dev only · no runtime changes vs 2b
หน้านี้คือ inspector สำหรับ artefacts ของ Phase 2b+ · โหลด contract JSON 4 ตัว · แสดง 5 use cases แบบ modeled · ไม่เรียก endpoint ใหม่. ทุก observation ต้อง consult planning page สำหรับ scope/non-scope/ deferred matrix.

Contract inspectors

loading…
loading…
loading…
loading…

5 Use cases (modeled)

UC-FF2B+-01

Verified vs decode-only JWT mode comparison

Request with Authorization: Bearer eyJ…. FF in verified mode requires JWKS + aud=pty-feature-flags · signature verified. FF in decode-only mode parses claims without verify and surfaces warnings.
expected ⇒ verified: allow · warnings=[] · auth_source=jwt ·· decode-only: allow · warnings=['auth_not_verified'] · auth_source=jwt_unverified
UC-FF2B+-02

Tenant override with current backing explanation

PUT /v1/flags/override/tenant/T-pty/ff.example (dev) · 2b+ writes to override JSON · in-memory dict updates · backing_state surfaced in response meta.
expected ⇒ 200 · meta.backing_state='file_backed' · meta.warnings=['dev_mode_only_write_path']
UC-FF2B+-03

User override precedence

Tenant override false + user override true → evaluation returns enabled=true · reason_chain=[user_override, tenant_override, default].
expected ⇒ enabled=true · reason='user_override_precedence' · source='file_backed'
UC-FF2B+-04

Cache invalidation / refresh semantics

2b+: no cache · each evaluate re-reads JSON. 2c (planned): Redis hit → meta.cache='hit' · invalidation broadcast on mutation keeps replicas consistent.
expected ⇒ 2b+ meta.cache='uncached' ·· 2c meta.cache='hit|miss' + invalidation event on channel ptt.ff.invalidate
UC-FF2B+-05

Sensitive flag gated via Admin 2b

Flag with sensitive_flag=true · requires_approval=true · approval_matrix_row=row-sensitive-override. FF consults Admin 2b /api/policy/sensitive.check.2b with approval_ref from JWT. Admin returns ttl_state=valid → allow with approval_ref in meta · ttl_state=expired → deny reason=approval_expired.
expected ⇒ valid: allow · meta.approval_ref='APP-…' · meta.ttl_state='valid' ·· expired: deny · reason='approval_expired' · suggested_action='request_fresh_approval'

Deferred matrix (live view)

Item
Current state
Why deferred
Next phase
Next
Phase 2c will: wire JWKS · migrate persistence to PostgreSQL · add Redis + invalidation publisher/subscriber · enable the cross-service call from FF to Admin 2b sensitive.check.2b · add audit sink delivery. Each step will have a parity pass against the 2b+ baseline before cutover.