Skip to content

feat: external SAP channels P1 foundation - #2142

Merged
jung-thomas merged 14 commits into
DEVfrom
channels-integration-p1
Sep 4, 2026
Merged

feat: external SAP channels P1 foundation#2142
jung-thomas merged 14 commits into
DEVfrom
channels-integration-p1

Conversation

@jung-thomas

Copy link
Copy Markdown
Contributor

External Channels — P1 foundation

Integrates the 238-channel SAP developer-channels research dataset into developers.sap.com as a living, DB-driven, re-ingestable subsystem. P1 scope only (foundation + ingestion + /channels directory + Surface A verb-lane fill + admin CRUD). P2–P4 (collections, topic crosswalk, submissions) are separate follow-up plans.

Spec: docs/superpowers/specs/2026-09-04-external-channels-integration-design.md
Plan: docs/superpowers/plans/2026-09-04-external-channels-p1-foundation.md

What's in this PR

  • Channels entity (db/channels.cds, com.sap.developers.ims) — source of truth; @assert.unique.sourceId, @assert.range enums, 4 array-of-String cols, curation columns (isPublished/isFeatured/editorialNote/linkStatusOverride…). Journaled via db/persistence.cds; aggregated in db/schema.cds.
  • Ingestionscripts/seed-channels.cjs (idempotent upsert on sourceId, preserves curated columns, soft retire-on-absence) + pure srv/lib/channels/normalize.js (cite-stripping, enum normalization, content hash).
  • Directory (Surface B)/build/channels read feed (srv/server.js, published + non-broken, parsed arrays) → scripts/fetch-channels.ts bakes hugo/data/channels.json (wired into build:all) → Hugo /channels page + Vue facet/search island (hugo-apps/src/channels-directory/).
  • Surface A verb-lane fillsrv/lib/channels/promote-to-shelves.js + scripts/promote-channels-to-shelves.cjs; community items never land in START_HERE (structural guard), uppercase HomepageVerb mapping, idempotent upsert on [verb,url], THIRD_PARTY badge.
  • Admin CRUDAdminService.Channels draft-enabled projection (XSUAA-guarded) + Fiori Elements app app/admin/channels/ wired into the admin shell (generator-driven manifest, nav entry).
  • Docs — new docs/developers/reference/channels.md + CLAUDE.md gotcha bullet.

Verification

  • npx cds deploy --to sqlite::memory: → exit 0.
  • Full unit suite on this HEAD: 9282 passed, 0 failed, 0 boot-hook timeouts (6 file failures were pre-existing env artifacts — gitignored srv-qa build output + an unbuilt sub-package's deps — none channels-related).
  • Built via subagent-driven-development: fresh implementer per task, per-task spec+quality review, final whole-branch review on the most capable model — APPROVED.

Follow-ups (non-blocking, for Tom's call)

  1. Directory facets narrower than spec §8.3/§10 — only category/platform/ownerScope+search are filterable; focusAreas & status are baked into channels.json but not yet wired as facets; per-channel card shows a single "Community" badge (no SAP-official/User-Group/Third-party split, no related-links display).
  2. /build/channels feed spreads the full row (...r) — managed audit + curation columns into the anon feed; no secrets, and matches the sibling /build/homepage-shelves pattern.
  3. Deferred Task-6 minors: CONNECT verb unreachable in FOCUS_TO_VERB; CATEGORY_TO_SHELF case-sensitive exact-match; mapChannelToShelf typed |null but never returns null (cosmetic).

Deploy note

Admin-shell changes are bundle-gated — require a FULL mbt build / npm run deploy (no --skip-build, no -m scoping) or the admin UI ships stale.

- Hugo section hugo/content/channels/_index.md + layout hugo/layouts/channels/list.html
  baking channels.json via .Site.Data.channels.channels into a <script type=application/json>
  data island; island referenced via island-src partial (content-hash safe)
- Vue 3 island hugo-apps/src/channels-directory/ with ChannelsDirectory.vue
  (faceted search: query, category, platform, ownerScope; community badge on non-SAP channels)
- Pure filterChannels() exported from filter.ts; filter.test.ts covers all filter axes (3/3 pass)
- Vite entry channels-directory registered in hugo-apps/vite.config.ts
- list.html: add | safeJS to jsonify pipeline so Go html/template emits
  the JSON value verbatim inside <script> rather than as a JS string literal
  (matches browse sibling pattern; without it JSON.parse returns a string,
  not an array, and the island renders zero cards)
- filter.test.ts: add YouTube fixture row so platform filter shows exclusion;
  add multi-facet combination it() proving rows must satisfy ALL active facets
  (query+ownerScope, category+ownerScope, ownerScope+platform); 4 tests now
Adds docs/developers/reference/channels.md covering:
- Channels entity (namespace, persistence journal, array columns, curated cols)
- seed-channels re-ingest CLI (idempotent upsert, preserve curated, retire-on-absence, flags)
- /build/channels feed → fetch-channels.ts → hugo/data/channels.json (wired into build:all)
- /channels Hugo directory page + channels-directory Vue island (filterChannels facets)
- promote-channels verb-lane fill (category→shelf, FOCUS_TO_VERB, community never START_HERE)
- AdminService.Channels projection + admin FE app + shell wiring via generate-manifest
- P1 scope / P2-P4 deferred items

Adds one Top Gotchas bullet in CLAUDE.md pointing to channels.md.
cds build --production regenerated db/last-dev/csn.json (adds the Channels
entity definition, +191 lines) and generated the new v1 migration table
db/src/com.sap.developers.ims.Channels.hdbmigrationtable. Required to make
the check-cds-build-staging CI gate green for the new persisted entity.
@jung-thomas
jung-thomas marked this pull request as ready for review September 4, 2026 17:42
@jung-thomas
jung-thomas merged commit c28aa67 into DEV Sep 4, 2026
9 checks passed
@jung-thomas
jung-thomas deleted the channels-integration-p1 branch September 4, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant