ms-ai-architect/docs/c3-course-detection-spike.md
Kjell Tore Guttormsen 792986820b docs(ms-ai-architect): C3 Fase 0 — Learn Platform API auth-oppsett + spike kartlagt; STATE → spec neste [skip-docs]
Sesjon 29: Platform API-beslutning (vs legacy/MCP), Entra app-only registrert
i privat tenant, creds i Keychain (secret-utløp ~2028-06), auth verifisert grønn.
Full API-kontrakt + 2 kritiske gotchas (updatedAt.gt krever full ISO; produkt-
slug azure-ai-foundry død) dokumentert i docs/c3-course-detection-spike.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:09:19 +02:00

35 lines
4.8 KiB
Markdown

# C3 Spike — Learn Platform API for kurs-deteksjon (Fase 0)
_Verifisert grunnlag for C3-spec-en. Skrevet 2026-06-23 (Sesjon 29). **Fase 0 = FERDIG** (auth-oppsett + full API-kartlegging). Neste økt: skrive `docs/c3-course-detection-plan.md` på dette grunnlaget. Ingen detektor-kode før spec er godkjent._
## Beslutning (operatør, S29)
Kurs-deteksjon (krav 3) bygges på **Microsoft Learn Platform API** (`/api/v1`, Entra ID app-only) — IKKE legacy `/api/catalog/` (anonym, deprekeres «starting June 2026») og IKKE microsoft-learn-MCP (docs-only, ingen dato/produkt-filter). MCP er feil verktøy; Platform API er future-proof. Begrunnelse: kunnskapskjernen skal stå på egne ben.
## Oppsett — FERDIG (engangs, operatørens private miljø)
- Entra-app `ms-ai-architect-learn-catalog` registrert i operatørens **private** Entra-tenant (single-tenant, ingen redirect-URI, **ingen API-tillatelser** — offentlig innhold krever ingen app-rolle; bekreftet ved at token virker uten).
- **Hemmeligheter i macOS Keychain** (account `ktg`): `learn-platform-client-secret` (utløp **~2028-06**, 24 mnd — eneste vedlikeholdspunkt), `learn-platform-tenant-id`, `learn-platform-client-id`. Aldri i repo/env. (Literal-IDer bevisst ikke i committet doc.)
- Auth verifisert grønn: client-credentials → token (scope `https://learn.microsoft.com/.default`) → HTTP 200 mot `/api/v1/modules`.
- **Detektoren leser creds rett fra Keychain ved kjøretid** (`security find-generic-password`) — ingen `~/.zshenv`/env-eksponering (strengere). Mønster bevist i efemert `/private/tmp/claude-learn-api-verify.sh` (slettes; reproduserbart).
## Verifisert API-kontrakt
- **Base:** `https://learn.microsoft.com/api/v1` · **påkrevd:** `?api-version=2023-11-01-preview` (kun preview-versjon finnes; kortere støttesyklus).
- **Per-type endepunkter** (ikke ett kombinert katalog-svar): `/api/v1/modules` ✅, `/api/v1/learning-paths` ✅ (**kebab-case**, ikke camelCase). `/api/v1/products`-taksonomi finnes IKKE (404).
- **Respons:** `{"value":[…], "nextLink":…}` — cursor-paginering via `nextLink`; `maxpagesize` ≤ 100 (default 30).
- **Modul-felt:** `id` (UID, stabil nøkkel), `title`, `updatedAt` (ISO 8601), `products[].id`, `roles[]`, `levels[]`, `subjects[]`, `units[]`, `url`, `summary`, `durationInMinutes`. Learning path: samme + `modules[]`.
- **Filter-semantikk:** flere params = AND; komma-separerte verdier i én param = OR. Produkt-filter virker **server-side** (`products=azure-openai` → 34 treff = ekte filtrering, ikke ignorert).
## Gotchas (MÅ håndteres i spec/kode — verifisert empirisk)
1. **`updatedAt.gt` krever FULL ISO 8601 datetime.** `updatedAt.gt=2026-01-01T00:00:00Z` → virker (100). Dato-only `updatedAt.gt=2026-01-01`**fail-closed (0 treff)**, til tross for at doc-eksempelet bruker dato-only. Dette er hjertet i currency-deteksjonen — pin formatet.
2. **Produkt-slugs må enumereres fra live data.** Doc-eksempelet `azure-ai-foundry`**0** (ikke en levende module-slug). Funnet i domenet (delvis, fra første 100 moduler): `ai-builder, microsoft-copilot-studio, ms-copilot, agent-365, power-automate, power-platform, power-apps, power-pages` + `azure-openai` (34 via filter). Siden `/api/v1/products` ikke finnes: enumerér ved å paginere alle moduler og samle distinct `products[].id`, eller finn et taksonomi-endepunkt.
3. **Deteksjonslogikk:** ny UID = nytt kurs · endret `updatedAt` = oppdatert kurs · forsvunnet UID = slettet. `updatedAt` endres IKKE ved minor edits (best-practices-doc).
4. **Locale:** `locale=nb-no` returnerer treff men faller tilbake til en-us-metadata der oversettelse mangler → bruk `en-us` som primær.
## Foreslått design for spec (til godkjenning neste økt)
- **Node-klient (Claude-fri, passer decision-ledger-arkitekturen):** Keychain-creds → token → paginer `/api/v1/modules` + `/api/v1/learning-paths` filtrert på domene-produkter + `updatedAt.gt=<sist kjørt, full ISO>` → diff mot lokalt register av kjente UIDs.
- **Output = leads inn i `decisions.json`** (operatør-gate): «disse nye/endrede kursene finnes i dine dekkede produkter — vurder om temaet bør dekkes i KB». IKKE auto-ingest av kursinnhold som KB-filer («oppdage … som bør dekkes»).
- **Skill-mapping:** produkt-slug → skill som **config**, ikke hardkoding (slug-sett finaliseres fra live taksonomi).
- **Arkitektur-invariant (uendret):** deteksjon skriver ALDRI til KB direkte; kun forslag via `decisions.json` etter operatør-gate. Scheduler-entrypoint strukturelt Claude-fri.
## Verifiseringskilder (offisielle)
- Platform API overview / get-started / developer-reference / best-practices / release-notes / FAQ — alle under `learn.microsoft.com/training/support/integrations-learn-platform-api-*`.
- Empirisk: probe-kjøringer mot live `/api/v1/modules` (S29), token-auth bekreftet.