From 1f5a5ced3ac581739357ba02ffa231cf6f324dfb Mon Sep 17 00:00:00 2001 From: DongHyeonka Date: Tue, 28 Jul 2026 14:21:30 +0900 Subject: [PATCH] =?UTF-8?q?docs(hub):=20gate=207=EA=B0=9C=EC=99=80=20?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=EB=B6=80=20=EC=B0=A8=EB=8B=A8(NOT=5FAPPLICAB?= =?UTF-8?q?LE)=20=EA=B0=9C=EB=85=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit capability 가 OFF 인 프로젝트에서 gate 를 PASS 라 하면 거짓말이고 FAIL 이라 하면 영원히 배포할 수 없다. NOT_APPLICABLE 을 도입하되 FE-GATE-033 이 번들 부재를 증명했을 때만 유효하게 묶었다. FE-GATE-033 자신은 NOT_APPLICABLE 을 취할 수 없다 — capability 를 하나도 쓰지 않는 프로젝트도 '쓰지 않는다'를 증명해야 한다. --- ...-skeleton-frontend-operational-contract.md | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/raw/project-notes/ca-skeleton-frontend-operational-contract.md b/raw/project-notes/ca-skeleton-frontend-operational-contract.md index 42faa19..6b482d0 100644 --- a/raw/project-notes/ca-skeleton-frontend-operational-contract.md +++ b/raw/project-notes/ca-skeleton-frontend-operational-contract.md @@ -1853,7 +1853,9 @@ Script 이름을 바꾸는 것은 허용되지만 acceptance gate와 artifact ma ### 15.1 Gate ownership -현재 stable gate registry는 26개 row이며, 새 gate를 추가하거나 supersede할 때 이 수와 promotion formula를 함께 갱신한다. +현재 stable gate registry는 33개 row이며, 새 gate를 추가하거나 supersede할 때 이 수와 promotion formula를 함께 갱신한다. + +`FE-GATE-027`~`FE-GATE-032`는 **capability-scoped gate**다. 대응 capability가 비활성이면 `NOT_APPLICABLE`을 취할 수 있으나, 그 상태는 `FE-GATE-033`이 PASS일 때만 유효하다(§18.1). > 이 표가 gate 의 **정의**다. `Covered FE-OC` 열은 gate 와 계약의 대응 관계이지 계약 내용의 사본이 아니다. > branch 는 이 표를 옮겨 적지 않는다 — gate ID 를 행 키로 쓰고 자기 control 만 적는다(예: [[raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract]]). @@ -1886,6 +1888,13 @@ Script 이름을 바꾸는 것은 허용되지만 acceptance gate와 artifact ma | `FE-GATE-024` | `FE-RB-004` drill | production promotion | `FE-OC-025` | `FE-NFR-010` | telemetry degradation | containment, escalation, recovery assertions pass | `FE-RB-004` record | `FAIL_UNVERIFIED` | | `FE-GATE-025` | `FE-RB-005` drill | production promotion | `FE-OC-025` | — | blocking release defect | rollback decision, escalation, recovery assertions pass | `FE-RB-005` record | `FAIL_UNVERIFIED` | | `FE-GATE-026` | lab performance | release | `FE-OC-021` | `FE-NFR-003`, `FE-NFR-004`, `FE-NFR-005` | recorded runner/throttling/cache context + named interactions | every lab threshold passes and report contains reproducibility metadata | lab performance report | `FAIL_UNVERIFIED` | +| `FE-GATE-027` | binary I-O & local store | merge | `FE-OC-013`, `FE-OC-027` | — | picker 취소·거부, quota 초과 fallback, OPFS 순차 write, Cache Storage 버전 파티션, object URL 해제 | 모든 fixture가 기대 kind로 처리되고 object URL 누수 0 | binary I-O report | `FAIL_UNVERIFIED` | +| `FE-GATE-028` | cache tier & cross-tab | merge | `FE-OC-012`, `FE-OC-028` | — | 영속 캐시 version 파티션, 탭 A mutation → 탭 B 무효화, BroadcastChannel 부재 fallback | 불일치 version 캐시는 복원되지 않고 탭 간 무효화가 도달 | cache tier report | `FAIL_UNVERIFIED` | +| `FE-GATE-029` | large object transfer | merge + release | `FE-OC-019`, `FE-OC-029` | `FE-NFR-018` | presign 만료, part 재시도 상한, stream 중단 후 재개, 무결성 불일치, credential 첨부 negative | 모든 fixture 통과 + 전송 요청에 session credential 0건 | transfer report | `FAIL_UNVERIFIED` | +| `FE-GATE-030` | multi-protocol transport | merge | `FE-OC-006`, `FE-OC-007`, `FE-OC-030` | — | GraphQL `200 + errors[]`, gRPC status ↔ HTTP status, codec decode 실패, gateway fallback | 모든 protocol 실패가 기대 kind로 정규화 | protocol mapping report | `FAIL_UNVERIFIED` | +| `FE-GATE-031` | realtime lifecycle | merge + release | `FE-OC-011`, `FE-OC-031` | `FE-NFR-016`, `FE-NFR-017` | 결정론 fake clock backoff, resume gap 감지, unmount 후 열린 연결(`SUBSCRIPTION_LEAKED` fixture), 이벤트 스키마 거부, `FE-RB-006` drill | backoff가 cap을 넘지 않고 unmount 후 열린 연결 0, 미검증 이벤트 0건 도달 | realtime lifecycle report | `FAIL_UNVERIFIED` | +| `FE-GATE-032` | background execution | merge + release | `FE-OC-016`, `FE-OC-017`, `FE-OC-032` | `FE-NFR-019` | SW 등록·갱신 UX, rollback 시 SW 되돌림, background sync keyed-only, worker timeout·terminate, `FE-RB-007` drill | 모든 fixture 통과 + keyed 아닌 mutation replay 0건 | background execution report | `FAIL_UNVERIFIED` | +| `FE-GATE-033` | capability default-off | merge + release | `FE-OC-004`, `FE-OC-022`, `FE-OC-027`, `FE-OC-028`, `FE-OC-029`, `FE-OC-030`, `FE-OC-031`, `FE-OC-032` | `FE-NFR-020` | 기본 config로 production build, 각 capability ON 조합 build | 비활성 capability의 adapter 모듈이 어떤 chunk에도 없고 initial JS 증가 0 | capability bundle report | `FAIL_UNVERIFIED` | ### 15.2 Negative fixture requirement @@ -1902,20 +1911,34 @@ Gate가 실제로 동작한다고 말하려면 최소 하나의 deliberately fai | release | HTML build A + asset manifest B | | reload guard | second chunk failure in same release pair | | lab performance | context metadata missing 또는 one named threshold exceeded | +| binary I-O | quota 초과인데 `UPLOAD_PART_STATE`가 memory로 fallback | +| cache tier | release/config version 불일치 캐시를 복원해 사용 | +| large object transfer | transfer 요청에 session credential 헤더가 첨부 | +| multi-protocol | `200 OK` + `errors[]`를 success로 반환 | +| realtime lifecycle | unmount 후에도 구독이 살아 있음 / 미검증 프레임이 application 도달 | +| background execution | `idempotency: none` mutation이 background sync로 replay | +| capability default-off | flag OFF인데 adapter가 initial chunk에 포함 | Negative fixture를 실행하지 않고 rule 존재만 확인한 결과는 `locally-verified` 증거로 부족하다. ### 15.3 Promotion rule ```text -MERGE_READY = FE-GATE-001, FE-GATE-002, FE-GATE-003, FE-GATE-004, FE-GATE-005, FE-GATE-006, FE-GATE-007, FE-GATE-008, FE-GATE-009, FE-GATE-010, FE-GATE-011, FE-GATE-013, FE-GATE-020 PASS +MERGE_READY = FE-GATE-001, FE-GATE-002, FE-GATE-003, FE-GATE-004, FE-GATE-005, FE-GATE-006, + FE-GATE-007, FE-GATE-008, FE-GATE-009, FE-GATE-010, FE-GATE-011, FE-GATE-013, + FE-GATE-020, FE-GATE-033 PASS + AND FE-GATE-027, FE-GATE-028, FE-GATE-030 각각 PASS 또는 유효한 NOT_APPLICABLE RELEASE_READY = MERGE_READY AND FE-GATE-012, FE-GATE-014, FE-GATE-015, FE-GATE-019, FE-GATE-026 PASS -PROD_PROMOTION_READY = RELEASE_READY AND FE-GATE-016, FE-GATE-021, FE-GATE-022, FE-GATE-023, FE-GATE-024, FE-GATE-025 PASS + AND FE-GATE-029, FE-GATE-031, FE-GATE-032 각각 PASS 또는 유효한 NOT_APPLICABLE +PROD_PROMOTION_READY = RELEASE_READY AND FE-GATE-016, FE-GATE-021, FE-GATE-022, FE-GATE-023, + FE-GATE-024, FE-GATE-025 PASS FIELD_SLO_READY = PROD_PROMOTION_READY AND FE-GATE-018 PASS DOCUMENTATION_READY = FE-GATE-017 PASS_SCOPED AND evidence ledger updated PROJECT_READY = all applicable blocking gates PASS ``` +`FE-GATE-033`은 `NOT_APPLICABLE`을 취할 수 없으므로 항상 `MERGE_READY`에 무조건 포함된다. capability를 하나도 쓰지 않는 프로젝트도 "쓰지 않는다"를 증명해야 한다. + 현재는 `PROJECT_READY = false`, 즉 `NOT_READY`다. --- @@ -2250,12 +2273,20 @@ To mark `prod-verified`: ```text PASS_STATES = {PASS, PASS_SCOPED} -READY iff every blocking row Current is in PASS_STATES +NOT_APPLICABLE = capability-scoped gate 가, 대응 capability flag 가 OFF 이고 + FE-GATE-033 이 그 adapter 의 번들 부재를 증명했을 때만 취할 수 있는 상태 +READY iff every blocking row Current is in PASS_STATES or is a valid NOT_APPLICABLE otherwise NOT_READY ``` `PASS_SCOPED`는 Blocking question과 Required evidence가 명시적으로 같은 제한 범위를 물을 때만 허용한다. 점수 평균으로 blocking failure를 상쇄하지 않는다. +`NOT_APPLICABLE`은 다음을 `MUST` 지킨다. + +- `FE-GATE-027`~`FE-GATE-032`**만** 취할 수 있다. `FE-GATE-033` 자신은 취할 수 없다. +- `FE-GATE-033`이 PASS가 아니면 모든 `NOT_APPLICABLE`은 무효이며 `FAIL_UNVERIFIED`로 강등된다. +- "안 쓴다"는 주장은 선언이 아니라 **번들에 그 adapter가 없다는 증거**로만 성립한다. + ### 18.2 Current scorecard | Readiness ID | Blocking question | Required evidence | Current | Reason | @@ -2268,7 +2299,7 @@ otherwise NOT_READY | `FE-RDY-006` | runtime config boot gate가 검증됐는가 | schema + boot tests | `FAIL` | test evidence `UNVERIFIED` | | `FE-RDY-007` | failure taxonomy가 test matrix로 강제되는가 | integration artifacts | `FAIL` | test evidence `UNVERIFIED` | | `FE-RDY-008` | auth boundary가 token lifecycle을 침범하지 않는가 | port/import tests | `FAIL` | implementation evidence 없음 | -| `FE-RDY-009` | 8 registry가 single owner로 구현됐는가 | registry snapshots | `FAIL` | implementation evidence 없음 | +| `FE-RDY-009` | 9 registry가 single owner로 구현됐는가 | registry snapshots | `FAIL` | implementation evidence 없음 | | `FE-RDY-010` | lint/checkJs/runtime-schema/unit/component/integration/e2e/a11y가 통과했는가 | CI artifacts | `FAIL` | CI evidence `UNVERIFIED` | | `FE-RDY-011` | build/bundle/security gate가 통과했는가 | release artifacts | `FAIL` | build evidence `UNVERIFIED` | | `FE-RDY-012` | lab·field NFR context와 측정값이 있는가 | lab + field reports | `FAIL` | target만 존재; `FE-GATE-018`, `FE-GATE-026`은 `FAIL_UNVERIFIED` | @@ -2276,6 +2307,7 @@ otherwise NOT_READY | `FE-RDY-014` | rollback drill이 수행됐는가 | drill record | `FAIL` | deploy/drill evidence `UNVERIFIED` | | `FE-RDY-015` | runbook이 실제 hosting command와 evidence path를 가지는가 | provider runbook | `FAIL` | provider 미정 | | `FE-RDY-016` | evidence ledger에 과장 없는 grade가 유지되는가 | ledger review | `PASS` | 현재 문서 경계 명시 | +| `FE-RDY-017` | 비활성 capability가 번들에서 실제로 부재한가 | capability bundle report | `FAIL` | build evidence `UNVERIFIED` | **Current verdict: `NOT_READY`**