{"schemaVersion":"developer.reits.tech/identity-security/v4","auditedAt":"2026-07-17T05:01:58Z","repository":"reits-auth","sourceCommit":"89acdf11b8dd5eae5b1cb69ea26dc5678a4c54d9","securityCommit":"cbe3da583de380a154ba22fcf01d37debc562ffa","sessionCommit":"f53239190bc38de03b266424e25101a0f60238b2","leastPrivilegeCommit":"89acdf11b8dd5eae5b1cb69ea26dc5678a4c54d9","previousRelease":"f747bb8c33fcc7d7f07226e56e18418ea32424f2","productionRelease":"89acdf11b8dd5eae5b1cb69ea26dc5678a4c54d9","openPlatformRelease":"fb1a1b45124f153ae685c9b5142b3186c98e5054","openPlatformWitnessSource":"fa9283d6c7ea964864d7a1b31035b03411802622","bookingRelease":"83d31a02d2030d7327adb4330803460fb47e84de","bookingWitnessSource":"83d31a02d2030d7327adb4330803460fb47e84de","endpoint":"https://auth.reits.tech","runtime":"Go · systemd · Nginx TLS · MySQL · EC2","listener":"127.0.0.1:8095","upstream":"im-core verification + MySQL session registry","decision":"controlled-cross-process-revocation-witness-passed","productionProven":false,"migrationBoundary":1784259900,"productionSessionRowsAtAudit":0,"productionSessionEventsAtAudit":0,"residualExposureUntil":"2026-07-24T03:45:00Z","policy":"K20 proves exact Auth and first-consumer allow-to-revoke-to-deny behavior in a controlled cross-process witness. It does not trigger production OTP, cover every resource server, or turn blueprint UI into product UI evidence.","summary":{"identityScreens":7,"currentPartial":4,"targetOnly":3,"securityControls":29,"sessionControls":8,"sourceTests":51,"journeyAssertions":17,"ciWorkflows":1,"passedGates":6,"partialGates":1,"blockedGates":1},"controls":[{"id":"AUTH-CFG-01","domain":"Runtime","control":"Production configuration preflight","before":"单个开关可启用 preview","now":"环境、监听、上游、密钥、TTL、preview 组合不安全即拒绝启动","evidence":"Config.Validate + ExecStartPre","status":"pass"},{"id":"AUTH-CFG-02","domain":"Runtime","control":"Loopback-only service","before":"*:8095","now":"127.0.0.1:8095，只通过 Nginx TLS 暴露","evidence":"EC2 socket + exact release","status":"pass"},{"id":"AUTH-OTP-01","domain":"Challenge","control":"Preview bypass removal","before":"allow/override/dev_code/fixed code 全开","now":"production 四项全部关闭，phone/wallet preview unavailable","evidence":"/v1/meta + negative smoke","status":"pass"},{"id":"AUTH-OTP-02","domain":"Challenge","control":"Challenge abuse bound","before":"无创建频率与失败次数上限","now":"每 client/kind/subject 5 次/10 分钟；单 challenge 最多 5 次失败","evidence":"race tests + external negative","status":"pass"},{"id":"AUTH-JWT-01","domain":"Token","control":"Issuer / audience / client binding","before":"仅验 HS256 签名与 exp","now":"固定 header、iss、aud=client、registered client、subject、sid、iat/exp","evidence":"cross-audience negative test","status":"pass"},{"id":"AUTH-JWT-02","domain":"Token","control":"Bounded session refresh","before":"过期 access token 可无明确边界刷新","now":"1h access、24h refresh_exp，刷新保留 sid/auth_time 且不能延长总边界","evidence":"refresh boundary tests","status":"pass"},{"id":"AUTH-API-01","domain":"API","control":"Safe request/response envelope","before":"query token、宽松 JSON、内部 URL metadata","now":"Bearer/POST only、strict JSON、no-store、request ID、内部 URL 脱敏","evidence":"handler negative tests + public meta","status":"pass"},{"id":"AUTH-API-02","domain":"API","control":"Compatibility profile binding","before":"caller header 可参与 profile 选择","now":"route 固定 client/kind；显式 browser Origin 必须在 client allowlist","evidence":"profile escalation negative test","status":"pass"},{"id":"AUTH-OPS-01","domain":"Operations","control":"Liveness / readiness split","before":"health 同时混入上游状态","now":"/healthz 只测进程；/readyz 同时要求 im-core 与 session-registry","evidence":"local + external smoke","status":"pass"},{"id":"AUTH-OPS-02","domain":"Operations","control":"Hardened release runtime","before":"可变 current 目录、弱 systemd sandbox","now":"immutable release、配置备份、回滚目录、systemd sandbox、HSTS","evidence":"release 89acdf1 + service journal","status":"pass"}],"sessionControls":[{"id":"AUTH-SES-01","domain":"Registry","control":"Durable session liveness","before":"JWT 自证存活","now":"auth_sessions 是 refresh/introspect/me 的在线权威；缺失、撤销、过期或不可用均 fail-closed","evidence":"MySQL migration + API tests","status":"pass"},{"id":"AUTH-SES-02","domain":"Issuance","control":"Persist before token return","before":"签名后直接返回","now":"会话成功持久化后才向调用方返回 JWT","evidence":"issue/store failure tests","status":"pass"},{"id":"AUTH-SES-03","domain":"Revocation","control":"Immediate Auth propagation","before":"只能等待 token 到期","now":"单会话、当前会话和其他会话撤销立即作用于 refresh/introspect/me","evidence":"revoke propagation tests","status":"pass"},{"id":"AUTH-SES-04","domain":"Isolation","control":"Subject + client inventory boundary","before":"无会话列表","now":"只列出当前 subject 与 client 的会话；不臆造设备、IP、UA","evidence":"ownership/client negative tests","status":"pass"},{"id":"AUTH-SES-05","domain":"Audit","control":"Append-only safe receipts","before":"无撤销回执","now":"create/revoke/noop 写入 auth_session_events；不记录 token、IP 或 User-Agent","evidence":"event table + idempotency tests","status":"pass"},{"id":"AUTH-SES-06","domain":"Capacity","control":"Active-session bound","before":"会话数量无上限","now":"每 subject + client 最多 20 个；始终保留最新并自动撤销最旧超额会话","evidence":"cap concurrency tests","status":"pass"},{"id":"AUTH-SES-07","domain":"Migration","control":"Bounded K17 enrollment","before":"上线会使全部已有会话失效","now":"只允许边界后的 K17 完整 claim 首次自注册；旧 Preview token 永不补录","evidence":"boundary/legacy negative tests","status":"pass"},{"id":"AUTH-SES-08","domain":"Operations","control":"Least-privilege runtime","before":"运行身份与迁移职责未分离","now":"DDL 由 operator 执行；Auth 账户仅 SELECT/INSERT/UPDATE/DELETE；readiness 检查 registry","evidence":"production grants + sidecar + external smoke","status":"pass"}],"consumerControls":[{"id":"AUTH-CON-01","service":"Open Platform","control":"Per-request active session","decision":"每个受保护请求直连 Auth introspection；正向缓存 0 秒","evidence":"fa9283d · no-cache contract · K20 cross-process witness","status":"pass"},{"id":"AUTH-CON-02","service":"Open Platform","control":"Exact client + route scope","decision":"client=developer-portal；GET apps 需 developer:read；所有 create/upload/publish 需 developer:write","evidence":"route middleware + wrong-client/scope negatives","status":"pass"},{"id":"AUTH-CON-03","service":"Open Platform","control":"Account + app ownership","decision":"Auth subject 映射 developer account；presign/upload/publish 继续校验 app owner","evidence":"request context subject + ensureOwner","status":"pass"},{"id":"AUTH-CON-04","service":"Booking","control":"Local session cannot outlive Auth","decision":"本地 tok_* 先解析但不信任；Auth active 后才进入 member/project/tenant owner 规则","evidence":"83d31a0 · member preflight · K20 cross-process witness","status":"pass"},{"id":"AUTH-CON-05","service":"Booking","control":"Bounded refresh + subject binding","decision":"过期 access 最多刷新一次；client=order-web；GET/HEAD 需 order:read，写请求需 order:write；email/IM UID 防漂移","evidence":"9 Node contract results · production invalid-token sidecar","status":"pass"},{"id":"AUTH-CON-06","service":"Edge / readiness","control":"Dependency-aware fail closed","decision":"inactive=401、client/scope/subject=403、Auth unavailable=503；公共只读接口不被身份故障拖垮","evidence":"openapi/order ready · Nginx public readiness · exact release","status":"pass"}],"consumerMatrix":[{"consumer":"Open Platform Developer API","release":"source fa9283d · runtime fb1a1b4","client":"developer-portal","read":"developer:read","write":"developer:write","subject":"im_core_uid + email → developer account","object":"app.owner_id","revocation":"K20 allow→revoke→next-request deny","readiness":"MySQL + Auth","state":"deployed"},{"consumer":"Booking member / merchant API","release":"83d31a0","client":"order-web","read":"order:read","write":"order:write","subject":"email or stored im_core_uid","object":"member → project / tenant / owner","revocation":"K20 allow→revoke→deny; bounded refresh","readiness":"Auth session authority","state":"deployed"},{"consumer":"OpenSDK bot / host integrations","release":"e50cb8a","client":"independent bot token","read":"consumer-specific","write":"consumer-specific","subject":"not reits-auth user session","object":"host/app binding","revocation":"separate credential lifecycle","readiness":"not in K19 first slice","state":"not-audited"},{"consumer":"Other resource servers","release":"—","client":"must be registered","read":"must be declared","write":"must be declared","subject":"must be bound","object":"tenant + resource owner","revocation":"must introspect or consume revoke event","readiness":"must include Auth when protected","state":"target"}],"consumerDecisionFixture":{"label":"DETERMINISTIC UI FIXTURE · PRODUCTION POLICY","request":{"service":"Open Platform","method":"POST","route":"/api/apps/upgrade/live","token":"Bearer ••••7A91","subject":"uid 42 · owner@example.com"},"steps":[{"id":"01","title":"Resolve route policy","detail":"developer-portal + developer:write","result":"MATCH"},{"id":"02","title":"Introspect Auth session","detail":"active · sid ses_k19 · no positive cache","result":"ACTIVE"},{"id":"03","title":"Bind principal","detail":"uid 42 + email → developer account","result":"BOUND"},{"id":"04","title":"Authorize object","detail":"app.owner_id = account.id","result":"OWNER"},{"id":"05","title":"Execute + receipt","detail":"publish only after every guard passes","result":"ALLOW"}],"failures":[{"code":"session_inactive","http":"401","action":"清理本地会话并重新登录"},{"code":"insufficient_scope","http":"403","action":"禁止执行；显示 required scope"},{"code":"auth_subject_mismatch","http":"403","action":"阻断主体漂移并记录 request ID"},{"code":"session_authority_unavailable","http":"503","action":"保护操作 fail closed；公共读取可继续"}]},"journeyControls":[{"id":"AUTH-JRN-01","control":"Exact cross-process code","decision":"启动 reits-auth 89acdf1，并调用两个仓库中的真实消费端实现，而不是复制策略 mock","evidence":"witness source revisions + 17 assertions","status":"pass"},{"id":"AUTH-JRN-02","control":"Two client sessions","decision":"同一合成主体分别签发 developer-portal 与 order-web 会话；audience/scope 不跨客户端复用","evidence":"same principal + two session refs","status":"pass"},{"id":"AUTH-JRN-03","control":"Allow → revoke → deny","decision":"每条 lane 先得到 ALLOW，再写入 revoke receipt，随后下一次消费端请求得到 typed deny","evidence":"2 allow + 2 receipts + 2 deny","status":"pass"},{"id":"AUTH-JRN-04","control":"Client isolation","decision":"撤销 developer-portal 会话后，order-web 会话仍保持 active，直到自身被撤销","evidence":"client-isolation assertion","status":"pass"},{"id":"AUTH-JRN-05","control":"No credential residue","decision":"仅允许 loopback HTTP；token 不持久化、不记录、不进入证据；challenge 不暴露 dev_code","evidence":"loopback guards + redaction assertions","status":"pass"}],"revocationWitness":{"schemaVersion":"developer.reits.tech/k20-revocation-witness/v1","generatedAt":"2026-07-17T05:01:58.099Z","evidenceClass":"controlled-cross-process","environment":"loopback-staging-memory","productionOtpTriggered":false,"allPassed":true,"assertionCount":17,"source":{"auth":"89acdf11b8dd5eae5b1cb69ea26dc5678a4c54d9","openPlatform":"fa9283d6c7ea964864d7a1b31035b03411802622","booking":"83d31a02d2030d7327adb4330803460fb47e84de"},"subject":{"kind":"synthetic-email","value":"k20.synthetic@reits.invalid","samePrincipalAcrossClients":true,"principalRef":"synthetic-im-core-uid:8693579137"},"tokenHandling":{"persisted":false,"logged":false,"includedInEvidence":false,"consumerTargets":"loopback-only"},"lanes":[{"consumer":"Open Platform Developer API","clientId":"developer-portal","release":"fa9283d6c7ea964864d7a1b31035b03411802622","requiredScope":"developer:write","sessionRef":"ses_4175ecba025a5cd17eca9d70","before":{"decision":"allow","code":"authorized"},"revoke":{"receiptId":"evt_a9301caa4f1a7c63914600f88597a0dc","revoked":true,"effectiveAt":1784264517},"after":{"decision":"deny","code":"session_inactive"},"nextRequestDenied":true},{"consumer":"Booking member / merchant API","clientId":"order-web","release":"83d31a02d2030d7327adb4330803460fb47e84de","requiredScope":"order:write","sessionRef":"ses_107764232c49a9715f3cb0f2","before":{"decision":"allow","code":"authorized"},"revoke":{"receiptId":"evt_ad97528be984ccbaec63bbd6c2ae94d0","revoked":true,"effectiveAt":1784264517},"after":{"decision":"deny","code":"auth_session_inactive"},"nextRequestDenied":true}],"isolation":{"developerRevokeLeftBookingActive":true,"reason":"subject is shared; client sessions and revocation remain isolated"},"assertions":[{"id":"auth.loopback-liveness","result":"pass","detail":"controlled process live"},{"id":"developer-portal.challenge","result":"pass","detail":"preview challenge created"},{"id":"developer-portal.secret-redaction","result":"pass","detail":"dev_code absent"},{"id":"developer-portal.issue","result":"pass","detail":"durable session issued"},{"id":"order-web.challenge","result":"pass","detail":"preview challenge created"},{"id":"order-web.secret-redaction","result":"pass","detail":"dev_code absent"},{"id":"order-web.issue","result":"pass","detail":"durable session issued"},{"id":"subject.same-principal","result":"pass","detail":"same synthetic im_core_uid"},{"id":"open-platform.allow-before","result":"pass","detail":"developer-portal + developer:write"},{"id":"booking.allow-before","result":"pass","detail":"order-web + order:write"},{"id":"open-platform.deny-after","result":"pass","detail":"session_inactive"},{"id":"client-isolation","result":"pass","detail":"order-web remained active after developer-portal revoke"},{"id":"booking.deny-after","result":"pass","detail":"auth_session_inactive"},{"id":"developer-portal.auth-introspect-deny","result":"pass","detail":"active=false"},{"id":"developer-portal.refresh-deny","result":"pass","detail":"401 reauthentication_required"},{"id":"order-web.auth-introspect-deny","result":"pass","detail":"active=false"},{"id":"order-web.refresh-deny","result":"pass","detail":"401 reauthentication_required"}],"productionBoundary":"This witness executes the exact Auth and consumer code in a controlled loopback staging process. It does not send a production email OTP and is not production-user evidence.","evidenceSha256":"d8096e7755a65a96f62dae92d5b1581901148f404b972f52ce8f5fe47ba10ef8"},"sessionWorkbench":{"label":"UI FIXTURE · NOT PRODUCTION DATA","productionRowsAtAudit":0,"states":["ready","empty","confirm","success","dependency-error"],"rows":[{"id":"ses_7F2A","client":"Open Platform","context":"当前浏览器","created":"刚刚","expires":"23h 58m","status":"CURRENT"},{"id":"ses_1C9D","client":"Open Platform","context":"设备信息待联邦关联","created":"昨天 09:42","expires":"6h 14m","status":"ACTIVE"}],"receipt":{"event":"session.revoked","result":"accepted","auditId":"evt_demo_A19C","note":"字段为确定性 UI fixture；不是生产回执"}},"screenReadiness":[{"screenId":"platform-auth-signin","title":"统一登录选择","state":"partial-current","implemented":["真实 im-core 邮箱 OTP","client/kind/origin 边界","生产 Preview fail-closed"],"missing":["企业身份","多身份选择 UI","完整返回上下文 consumer evidence"],"nextGate":"Web READY/ERROR/FORBIDDEN fixture + real login synthetic"},{"screenId":"platform-auth-otp","title":"OTP 验证","state":"partial-current","implemented":["challenge create/verify","600s TTL","创建限流与五次失败锁定"],"missing":["持久化/多实例 challenge","真实 OTP E2E artifact","重发/倒计时/a11y UI fixture"],"nextGate":"Redis atomic store + consumer state matrix"},{"screenId":"platform-auth-mfa","title":"强认证","state":"target-only","implemented":[],"missing":["Passkey","认证器","可信设备确认","恢复码","高风险动作 step-up"],"nextGate":"MFA contract + provider + negative suite"},{"screenId":"platform-auth-sessions","title":"设备与会话","state":"partial-current","implemented":["MySQL durable Session Registry","会话列表与 current/single/others revoke","撤销事件回执与 20 会话上限","K17 有界迁移","Booking / Open Platform 下一请求传播","K20 受控跨进程 allow→revoke→deny 见证"],"missing":["产品会话管理 UI","设备/IP/UA 与 im-core 联邦关联","其他资源服务器传播","签名密钥轮换","经授权的生产邮箱 OTP 会话旅程"],"nextGate":"产品 UI evidence + approved production OTP synthetic + remaining consumers"},{"screenId":"platform-auth-consent","title":"Scope 与授权确认","state":"target-only","implemented":[],"missing":["ConsentRequest","逐项能力用途","授权期限","撤销回执"],"nextGate":"资源授权模型先于 UI"},{"screenId":"platform-auth-recovery","title":"账号恢复","state":"target-only","implemented":[],"missing":["可信设备恢复","安全等待期","人工复核","恢复状态与保留策略"],"nextGate":"统一恢复 owner + privacy retention"},{"screenId":"platform-forbidden","title":"无权限与受限资源","state":"partial-current","implemented":["issuer/audience/client 拒绝","Origin 拒绝","撤销/缺失 session_inactive","安全 401/403/503 envelope","Open Platform app owner + Booking project/tenant owner"],"missing":["统一 AuthorizationDecision schema","访问申请","组织角色关系","全资源服务器覆盖"],"nextGate":"扩展 consumer matrix 并注册统一 decision receipt"}],"gates":[{"gate":"G1","name":"Scope","status":"pass","evidence":"K20 controlled journey · Auth + 2 consumer repos · 7 Screen ID impact"},{"gate":"G2","name":"Static","status":"pass","evidence":"gofmt · go vet · static build · config/store check"},{"gate":"G3","name":"Unit","status":"pass","evidence":"15 Auth race tests + two loopback witness guards · registry/revoke/migration negatives"},{"gate":"G4","name":"Contract","status":"pass","evidence":"K19 17 consumer checks + K20 17/17 cross-process assertions；two client lanes"},{"gate":"G5","name":"Experience","status":"blocked","evidence":"本页为 UI fixture；7 个产品 UI 九态、visual、a11y、interaction 尚未接入"},{"gate":"G6","name":"Security","status":"pass","evidence":"preview/audience/origin/registry/ownership/revoke/legacy-enroll negatives"},{"gate":"G7","name":"Release","status":"pass","evidence":"exact SHA · additive migration · least privilege · immutable rollback"},{"gate":"G8","name":"Production","status":"partial","evidence":"精确代码受控旅程已通过；生产 release/readiness 正常；仍未获授权执行真实邮箱 OTP 用户旅程"}],"flows":[{"id":"01","title":"Production email OTP","steps":["Client + allowed route","subject limiter","im-core send/check","login-user","persist session","bound JWT"],"guard":"任何上游或 registry 失败都不能返回 token 或回退 fixed code"},{"id":"02","title":"Durable issue / refresh","steps":["Verify claims","Find active session","Match client/subject/scopes","Enforce refresh_exp","Cap new exp","Return bounded JWT"],"guard":"数据库不可用、记录缺失或边界不匹配一律 session_inactive"},{"id":"03","title":"Inventory / revoke","steps":["Authenticate current session","List same subject + client","Confirm impact","Revoke one/current/others","Append receipt","Deny next Auth use"],"guard":"撤销幂等；不跨 client，不把 token/IP/UA 写入事件"},{"id":"04","title":"Release / rollback","steps":["Exact Gitea SHA","Operator migration","Least-privilege preflight","Side-port checks","Atomic current switch","External smoke"],"guard":"失败恢复 env/unit/nginx/current；additive schema 可留存"},{"id":"05","title":"Consumer authorization","steps":["Resolve client + route scope","Introspect active session","Bind local subject","Check tenant / object owner","Execute or typed deny"],"guard":"无正向撤销缓存；401/403/503 不混淆；Auth 故障不允许保护操作继续"},{"id":"06","title":"Cross-process revocation witness","steps":["Start exact Auth binary","Issue two client sessions","Run real consumer allow","Revoke each session","Run next-request deny","Verify refresh/introspection deny"],"guard":"仅 loopback staging；token 不落盘/日志/证据；不能冒充生产 OTP 证明"}]}