diff --git a/CLAUDE.md b/CLAUDE.md index 55294fb..423134e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -18,6 +18,10 @@ tenant running the same code paths. LearnStack ships in three production deployment modes — SaaS, Dedicated, Self-Hosted — backed by the companion **`learnstack-hub`** repository (separate repo, see [ADR-0019](docs/decisions/0019-learnstack-hub.md)). +The Hub repo lives at sibling path `../learnstack-hub` on developer +workstations; GitHub: https://github.com/cemililik/LearnStack-Hub. +Phase 02c P02c-0 (Hub repo bootstrap) shipped 2026-05-21 — see the +Phase 02c roadmap doc for the per-packet status. ## What state this is in diff --git a/README.md b/README.md index c6d0353..dd8b498 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,11 @@ LearnStack ships in three production deployment modes — SaaS, Dedicated, Self- backed by the companion **`learnstack-hub`** repository which provides the SaaS / Dedicated control plane, plan editor, custom-domain admin, and license-key issuance. +The Hub repo is expected to live at `../learnstack-hub` (sibling to this repo on the +developer's workstation) so the cross-repo doc cross-links resolve. See +[learnstack-hub on GitHub](https://github.com/cemililik/LearnStack-Hub) and +[docs/roadmap/phase-02c-hub-foundation.md](docs/roadmap/phase-02c-hub-foundation.md). + ## Status Phase 01 complete. The repository now holds the .NET 10 solution scaffold (7 diff --git a/docs/roadmap/phase-02c-hub-foundation.md b/docs/roadmap/phase-02c-hub-foundation.md index 54b4ff0..61d14d9 100644 --- a/docs/roadmap/phase-02c-hub-foundation.md +++ b/docs/roadmap/phase-02c-hub-foundation.md @@ -1,5 +1,69 @@ # Phase 02c: LearnStack Hub Foundation (parallel track) +> **Status (2026-05-21).** Phase 02c in progress. +> +> **P02c-0 — Repository bootstrap ✅** +> Sibling `learnstack-hub` git repository created (GitHub: +> https://github.com/cemililik/LearnStack-Hub). Backend solution +> (`LearnStack.Hub.slnx`) with 7 core projects + 4 test projects builds +> green (0 warnings, 0 errors); 4 architecture tests + 1 smoke test pass. +> Frontend pnpm monorepo (`apps/operator-portal` + `packages/{config,sdk,ui}`) +> typechecks, lints, and builds. Hub-side compose stack +> (Dapr placement + sidecar on 50006 / 3501 / 50002, APISIX on 9180, +> Postgres init for the `learnstack_hub` database) declared; shares +> LearnStack core's Postgres / Valkey / Vault / Kafka / Keycloak / Mailpit +> via `host.docker.internal`. Hub CI workflow (backend + frontend + meta +> + secret-scan) mirrors LearnStack core's shape. Documentation skeleton +> in place: `docs/architecture/contract-with-learnstack.md` points to +> LearnStack-side authority for the four-endpoint contract surface; +> `docs/decisions/` reserves the `HUB-NNNN` Hub-internal ADR series; +> `docs/glossary.md` covers Hub-specific terms. No Hub domain code yet — +> that lands in P02c-1. +> +> **P02c-1 — Hub Domain Core ⏳ Next** +> `LearnStackTenant` (mirror), `Plan`, `HubSubscription`, `Entitlement` +> aggregates + per-module DbContexts + initial EF migrations; Hub-side +> equivalent of LearnStack core P02a-2 (SharedKernel: `Result`, +> `Entity`, `IClock`, Vogen) + P02a-3 (cross-cutting foundation). +> `Hub_NeverStores_TenantData` and +> `Hub_Modules_DoNotReference_LearnStack_Internals` architecture tests +> become real once modules land. +> +> **P02c-2 — Hub-side Internal API + Outbound `LearnStackApiClient` ⏳** +> `POST /api/v1/internal/license/verify` + `POST /api/v1/usage/report` +> handlers, mTLS + signed JWT + HMAC body-signature chain, Hub OpenAPI +> spec generation + frontend SDK generation. +> +> **P02c-3 — LearnStack core PR ⏳ blocked on LearnStack P02a-5/6/7/9** +> `HubEntitlementProvider` (production-complete) + `IUsageReporter` +> adapter on the LearnStack side; APISIX `/api/internal/*` stub activation; +> `POST /api/internal/tenants` + `PUT /api/internal/tenants/{id}/entitlements` +> handlers; Dapr `learnstack.hub.entitlement` consumer; architecture test +> catalogue migration of `LearnStack_Modules_DoNotReference_Hub` + +> `IEntitlementProvider_Implementations_Are_Three` + +> `NullEntitlementProvider_NotRegistered_OutsideDevelopment`. +> +> **P02c-4 — Operator Portal MVP ⏳** +> Keycloak `learnstack-hub` realm OIDC + PKCE BFF login, tenant list +> (filterable), tenant detail (entitlement read-only viewer), plan list +> (read-only), dashboard stub. MFA enforced. +> +> **P02c-5 — Custom Domain Lifecycle ⏳** +> `CustomDomain` aggregate + state machine, DNS-01 / HTTP-01 challenge +> runner, Let's Encrypt provider adapter, +> `learnstack.hub.custom-domain.activated/.deactivated/.renewed` event +> publish; LearnStack-side `platform_host_to_tenant` mirror handler per +> ADR-0022 Amendment 1 (Hub never writes LearnStack K8s state). +> +> **P02c-6 — License Key (functional skeleton) ⏳** +> `LicenseKey` aggregate + RSA-2048 keypair + `.lic` file format +> (JWT-style claims); LearnStack-side `SignedLicenseKeyEntitlementProvider` +> skeleton. +> +> **P02c-7 — End-to-End Exit Gate ⏳** +> Full SaaS scenario + Self-Hosted bootstrap rehearsal; Hub + LearnStack +> architecture suites green. + ## Goal Bootstrap the **separate `learnstack-hub` repository** and stand up the foundation