diff --git a/CLAUDE.md b/CLAUDE.md index 5524b4750..e996b5228 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -159,4 +159,4 @@ The load-bearing few. **Full detail for every relocated item → [tutorials-ims- - **External channels subsystem** — `Channels` entity (`db/channels.cds`) is the source of truth; re-ingest via `npm run seed-channels`; directory at `/channels` (baked by `fetch-channels` in `build:all`); verb-lane fill via `npm run promote-channels`; community items never land in `START_HERE`. → [channels.md](docs/developers/reference/channels.md). - **TechEd sessions subsystem (#2312)** — new `TechEd*` entities (`db/external/teched.cds`, NOT reused `CommunityEvents`), loaded via a **`using` side-effect** in `db/external-content.cds` (don't delete the import); RainFocus ingest (`POST https://events.rainfocus.com/api/sessions`, headers `rfapiprofileid`/`rfwidgetid` per venue from `RAINFOCUS_{TE26,TEV26}_PROFILE`/`_WIDGET` env — live-confirmed defaults baked in, IDs may rotate; speakers embedded in `participants[]`, tracks in `attributevalues[attribute=="Track"]`, offset-paginated); idempotent seed via `scripts/seed-teched.cjs`; public `/build/teched` feed; corrected fetcher + delta cron jobs shipped in #2332; `/teched/` page + island, KG projection, embeddings, and Devtoberfest cross-linking are later units. → [teched.md](docs/developers/reference/teched.md). - **Signed provenance envelope (#2245)** — `PROVENANCE_ENVELOPE_ENABLED` (DB config, default OFF, DEV-first); two anonymous Express endpoints (`/content/tutorials/:slug/provenance` and `/.well-known/tutorial-provenance/jwks.json`); signing key = `PROVENANCE_SIGNING_KEY` credstore secret (Ed25519 PKCS8 PEM); rotate via `/admin-ui/#secrets`. Fail-open. → gotchas.md "Signed provenance envelope". -- **Optimized draft deletion `draft_admin_integrity` ON (#2909, CAP 10.2)** — `cds.fiori.draft_admin_integrity: true` in package.json; draft discard cascade-deletes draft `CompletionPathItems`/`GroupPathItems` at the DB level, so rollup reconcile now fires via `after('DISCARD','Missions.drafts'/'Groups.drafts')` (the `.drafts` target is required), NOT the per-row child `after('DELETE')` hooks (those stay for direct programmatic deletes). Deleting an active entity right after `draftActivate` can 403 ("a draft exists") until the residual draft is discarded. Constraint migration deploys to HANA (`.hdbconstraint`, `NOT VALIDATED`) BEFORE the flag serves. → gotchas.md "Optimized draft deletion". Re-enable runbook: docs/developers/operations/draft-integrity-reenable.md. +- **Optimized draft deletion `draft_admin_integrity` is OFF (#2909 / #2993, CAP 10.2)** — `cds.fiori.draft_admin_integrity: false` in package.json (all profiles). It was briefly enabled but shipped to PROD WITHOUT the required HANA `ON DELETE CASCADE` constraints, orphaning draft rows and making missions un-editable (`DRAFT_ALREADY_EXISTS` / `Not Found`, no discard affordance) — the 2026-11-02 PROD outage. Disabled for all profiles; draft deletion uses the pre-10.2 per-row `after('DELETE')` child hooks + `after('DISCARD')` root reconcile. The real draft shadow tables are `ADMINSERVICE_*_DRAFTS` (NOT `com_sap_developers_ims_*_drafts`). Orphan sweep: `scripts/cleanup-draft-orphans.cjs --commit` (deletes draft rows whose `DraftAdministrativeData_DraftUUID` has no admin-data parent; preserves live drafts). Re-enabling the `dad` strategy is blocked on an unresolved HDI make-graph problem for the cascade `.hdbconstraint` (inline FK → error 8250014; standalone constraint → 8212001 on delta deploy) — tracked in #2993; the flag must stay OFF until that deploys cleanly to a real HANA container. → gotchas.md "Optimized draft deletion". Re-enable runbook: docs/developers/operations/draft-integrity-reenable.md.