feat(leidangr): Phase 2 Backstage skeleton - design, plan, BDD features, adapter, registration#18
Conversation
…ao to Gitea) Brainstormed design for the first slice of Leidangr Phase 2 — a fresh modern Backstage component (codenamed leidangr) that runs locally with a strong DevEx envelope. Key decisions captured: - Two checkpoints — a zero-secret green stub boot, then an OpenBao to Gitea catalog loop. - Secrets via a provider-agnostic scripts/dev-secrets using OpenBao OIDC browser login against the existing Keycloak, rendering a gitignored .env.local. The running app stays agnostic to which OpenBao (local k3s or GKE) backs it. - Three first-class modes — stub/mock default with zero secrets, local-secrets, and a future deployed path via ESO. - Portability as a hard rule — Makefile plus scripts run standalone or under GDD, never depending on the workspace. - BDD from day one (jest-cucumber) over TDD'd TypeScript envelope tooling. - ADRs as MADR files from decision one, with the GitHub-only ADR plugin deferred. Out of scope for this slice: Keycloak sign-in to Backstage, GitHub, custom plugins, scorecards, the realm facility/calendaring/event-template modeling, CI, and in-cluster deploy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Records the contributor/no-port-forward path surfaced in review. Browser-OIDC needs both the browser to reach Keycloak and the bao CLI plus callback to reach the OpenBao API, so contributors without port-forward rights need OpenBao reachable at a direct URL — not just Keycloak exposed. Adds: - a two-paths-one-script reachability note (port-forward for owners, BAO_ADDR direct URL for contributors, selected by config) - a live-phase contributor-access section with the security shape (TLS via the shipped wildcard, Keycloak-group to read-only policy on the dev scope, short-lived tokens, audit) and Tailscale as a lower-exposure option - a matching open item The skeleton slice is unchanged — still port-forward on the owner's own cluster. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step-by-step implementation plan for the leidangr Backstage skeleton, plus the two BDD feature files written as external artifacts the plan points at (rather than copy-paste code blocks). Plan structure: - Task 1 scaffold create-app (interactive — not unattended) + repo hygiene - Task 2 tested doctor + Makefile envelope - Task 3 jest-cucumber harness + checkpoint-1 acceptance (stub boot) - Task 4 config layering + zero-secret stub guarantees - Task 5 tested dev-secrets logic (target resolve / validate / render) - Task 6 Gitea integration + checkpoint-2 acceptance (mocked; @LiVe deferred) - Task 7 MADR v3 ADRs for the decisions - Task 8 live wiring runbook + Gitea seed + realm registration Feature files (tests/acceptance once scaffolded): - checkpoint-1-stub-boot.feature — config valid without secrets, doctor, catalog example - checkpoint-2-openbao-gitea.feature — dev-secrets render/validate/target, Gitea ingest, @LiVe The plan and features cover Tasks 1-7 with no cluster needed. Only the @LiVe step (Task 8) needs OpenBao unsealed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the realm adapter so `ws test leidangr` and `ws lint leidangr` work (allowlisted, no repetitive raw commands): - test: corepack yarn jest --config jest.envelope.config.cjs (the DevEx envelope + BDD acceptance suite) - lint: corepack yarn backstage-cli repo lint The component is declared locally in ecosystem.local.yaml for now (unpushed); it moves into the realm ecosystem at registration (leidangr phase-2 Task 8). The generated app/backend unit tests run via `ws exec leidangr corepack yarn backstage-cli repo test`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Declares the leidangr Backstage control-plane in the realm ecosystem now that it lives at github.com/SiliconSaga/leidangr (repo derived from defaults.gitOrg + name). Local-first skeleton today (not cluster-deployed); declared so the workspace can clone/exec/commit/test it. Pairs with adapters/leidangr.yaml. Supersedes the temporary local-only declaration in ecosystem.local.yaml. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 5 minutes. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds planning artifacts for Leidangr Phase 2: a new ChangesLeidangr Phase 2 Backstage Skeleton Planning
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/plans/2026-06-21-leidangr-phase2-backstage-skeleton-design.md`:
- Around line 4-6: Update the plan document to reflect the current
implementation flow rather than the old draft workflow. Replace the “pending
implementation plan” status in the header and revise the note about `leidangr`
registration so it matches the new `ecosystem.yaml`-based registration that
already exists. Keep the wording aligned with the rest of the document’s Phase 2
slice description and remove any text that implies registration happens only
after a green boot.
In `@docs/plans/2026-06-21-leidangr-phase2-backstage-skeleton-plan.md`:
- Around line 503-506: The realm registration step is still ambiguous about
where `leidangr` should be declared, so update the plan entry for this
registration to explicitly pin `leidangr` to tier 3. Use the existing “Step 4:
Register the component in the realm” section as the anchor, and replace the
“tier 2/3 as appropriate” wording with the explicit tier-3 ecosystem component
contract so the declaration matches the PR objective.
- Around line 394-403: Harden the secret handling in validateKeys and
renderEnvLocal by treating blank or whitespace-only values as missing, not just
absent keys, so required secrets cannot pass validation empty. Update
renderEnvLocal to safely emit dotenv content by escaping or quoting values that
contain special characters, newlines, or leading/trailing spaces, and keep the
logic aligned with validateKeys so only truly present values from the mapping
are rendered.
- Around line 412-413: The `scripts/dev-secrets` flow is nondeterministic
because the background `kubectl port-forward` is started without confirming
readiness or ensuring cleanup, which can cause flaky `make secrets` runs and
port collisions on 8200. Update the script logic around the
port-forward/bootstrap steps to wait until the forwarded endpoint is actually
ready before continuing, and ensure the background process is reliably
terminated afterward; keep the existing `BAO_ADDR`/`kubectl` resolution, `bao
login`, `bao kv get`, and `.env.local` rendering behavior intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e9ff9c70-e497-4836-9d0e-8a0f7cb11111
📒 Files selected for processing (6)
adapters/leidangr.yamldocs/plans/2026-06-21-leidangr-phase2-backstage-skeleton-design.mddocs/plans/2026-06-21-leidangr-phase2-backstage-skeleton-plan.mddocs/plans/2026-06-21-leidangr-phase2-features/checkpoint-1-stub-boot.featuredocs/plans/2026-06-21-leidangr-phase2-features/checkpoint-2-openbao-gitea.featureecosystem.yaml
Two accuracy fixes from CodeRabbit on PR #18: - design status was still "Draft / pending implementation plan" and described registration as happening only after a green boot — both superseded now that the plan and the ecosystem.yaml registration are in this PR. - plan Step 4 said "tier 2/3 as appropriate"; pinned to tier 3 to match the actual registration. The two hardening comments (validateKeys/renderEnvLocal, port-forward) target the plan's illustrative code snippets; the canonical implementation is already hardened in component PR #1, and the plan is a point-in-time artifact per the realm convention (plans distill to ADRs and age out), so the snippets are left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Registers the new Leiðangr component in the SiliconSaga realm and adds the realm-side artifacts (design/plan + BDD feature specs + ws adapter) that describe and drive the Phase 2 “Backstage skeleton” work that lives in the separate SiliconSaga/leidangr component repo.
Changes:
- Add
leidangras a tier-3 component inecosystem.yamlfor workspace cloning/testing. - Add BDD
.featurespecs and accompanying design + execution plan docs for the Phase 2 Backstage skeleton slice. - Add a
wsadapter to standardizews test leidangr/ws lint leidangrcommands.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| ecosystem.yaml | Registers leidangr in the realm ecosystem as a tier-3 component. |
| adapters/leidangr.yaml | Adds ws adapter commands and AI context pointers for the leidangr component repo. |
| docs/plans/2026-06-21-leidangr-phase2-backstage-skeleton-design.md | Documents the design rationale and scope for the Backstage skeleton slice. |
| docs/plans/2026-06-21-leidangr-phase2-backstage-skeleton-plan.md | Provides the task-by-task implementation plan for the component work. |
| docs/plans/2026-06-21-leidangr-phase2-features/checkpoint-1-stub-boot.feature | Adds Checkpoint 1 acceptance criteria (zero-secret stub boot). |
| docs/plans/2026-06-21-leidangr-phase2-features/checkpoint-2-openbao-gitea.feature | Adds Checkpoint 2 acceptance criteria (OpenBao → Gitea catalog loop). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| **Architecture:** A `@backstage/create-app` monorepo wrapped in a thin root platform envelope (`Makefile` + `scripts/`). The running app is secret-store-agnostic: it consumes only env vars rendered by `scripts/dev-secrets`, which is the single local retrieval path. Two checkpoints — a zero-secret stub boot, then the OpenBao→Gitea loop. BDD (jest-cucumber) drives acceptance over TDD'd TypeScript envelope tooling. | ||
|
|
||
| **Tech Stack:** Backstage (new frontend + backend systems), Node Active LTS (22), Yarn 4 (Corepack), TypeScript, Jest + `@backstage/backend-test-utils`, jest-cucumber, OpenBao (`bao` CLI, OIDC auth via Keycloak), Gitea integration, SQLite (dev DB). |
|
|
||
| ## Global Constraints | ||
|
|
||
| - **Node:** Active LTS, pinned to **22** via `.nvmrc`/`.node-version`. Yarn 4 via `corepack enable`. |
| - [ ] **Step 1: Wire the Gitea integration (token via `$env`)** | ||
|
|
||
| ```yaml | ||
| # app-config.yaml (additions) | ||
| integrations: | ||
| gitea: | ||
| - host: gitea.localhost | ||
| token: ${GITEA_TOKEN} | ||
| catalog: | ||
| locations: | ||
| - type: url | ||
| target: https://gitea.localhost/leidangr/catalog-seed/raw/branch/main/catalog-info.yaml | ||
| ``` |
| # Leiðangr Phase 2 — Backstage Skeleton + DevEx (first slice) | ||
|
|
||
| **Date:** 2026-06-21 | ||
| **Status:** Implemented — component PR [SiliconSaga/leidangr#1](https://github.com/SiliconSaga/leidangr/pull/1); realm registration in this PR. |
|
Skipping copilot comments as aimed at stale planning docs |
Summary
Realm-side artifacts for Leiðangr Phase 2 — the Backstage skeleton. The component itself is SiliconSaga/leidangr#1.
docs/plans/2026-06-21-leidangr-phase2-backstage-skeleton-{design,plan}.md— the local-first Backstage skeleton (zero-secret stub boot, then an OpenBao-to-Gitea catalog loop), taken through the brainstorm to writing-plans flow, including the contributor / OpenBao-exposure refinement.docs/plans/2026-06-21-leidangr-phase2-features/checkpoint-{1,2}-*.feature— the executable acceptance specs the plan points at.adapters/leidangr.yaml— wiresws test/ws lint leidangr.leidangr(tier 3) added toecosystem.yaml, superseding a temporary local-only declaration.Test plan
ws actions leidangrshows the adapter commands "from realm".ws test leidangrruns the envelope + BDD suite (18/18 green).Related