mdview
Notes
Review 2
-
Review: [Ch 7] Services wiring — Keycloak realm and OIDC client
review-1948-2026-08-01Verdict: NEEDS_REFINEMENT
Template Completeness
- [x] Type — Feature
- [x] Lineage
- [x] Repo
- [x] User Story
- [x] Context
- [x] File Targets
- [x] Feature Flag — "none" (infra provisioning, acceptable)
- [x] Acceptance Criteria
- [x] Test Expectations
- [x] Constraints
- [x] Checklist
- [x] Related
Traceability
- [x] story:full-stack label — "Register READMEs via CLI, browse on phone via iOS app with Keycloak auth"
- [x] story note verified — found in project-mdview user-stories section
- [x] arch:mdview-infra label — infrastructure component
- [ ] arch note MISSING — [SCOPE] Create architecture note arch-mdview-infra. Note returned 404 from pal-e-docs.
- [x] Forgejo issue — ldraney/mdview#17, state: open
File Targets
- [ ]
pal-e-services/terraform/keycloak.tf— ISSUE: keycloak.tf contains HCL resource definitions that usevar.keycloak_realmsandvar.keycloak_clients. The actual realm/client VALUES are populated in the tfvars file (e.g., pattern ink3s.tfvars.example). The file target should reference the tfvars file wherekeycloak_realmsandkeycloak_clientsentries are added, not keycloak.tf itself. - [ ]
pal-e-deployments/overlays/mdview/prod/secrets.enc.yaml— ISSUE: This file does not exist yet. The issue says "add KEYCLOAK_* env vars" implying modification, but the file needs to be created. The SOPS-encrypted pattern exists in other overlays (e.g.,overlays/landscaping-assistant/prod/secrets.enc.yaml). - [ ] MISSING:
pal-e-deployments/overlays/mdview/prod/kustomization.yaml— currently only references../base. Must be updated to include the new secrets.enc.yaml as a resource. - [ ] MISSING: No file target references the
keycloak_clientsvariable entry. AC #2 requires an OIDC client with PKCE, but the file targets only mention the realm (keycloak_realms). The client is a separate variable/resource.
Repo Placement
MISMATCH: Issue filed on
ldraney/mdviewbut all file targets are inldraney/pal-e-servicesandldraney/pal-e-deployments. The mdview repo itself has zero file targets. Existing board pattern filed infra issues on the target repos (item #1243 on pal-e-services/issues/99, item #1244 on pal-e-deployments/issues/174). Consider splitting into separate issues on the target repos or documenting why this cross-repo filing is intentional.Dependencies
- Upstream (done): Items #1243 (var.services entry), #1244 (kustomize overlay), #1245 (RAILS_MASTER_KEY), #1246 (ArgoCD sync) — all in "done" column. Infrastructure foundation is in place.
- Downstream: Item #1951 [Ch 11] "Integration — auth, database, and API token generation" (8 pts, backlog) depends on this ticket. Ch 11 wires the app to use the Keycloak realm created here.
- Parallel: Item #1947 [Ch 6] "Database provisioning — CNPG for API tokens and sessions" (3 pts, backlog) — independent but both feed into Ch 11.
- Dependencies are not documented in the issue body.
Acceptance Criteria
4 criteria — all verifiable via
tofu planoutput and file inspection. However:- AC #4 lists KEYCLOAK_URL, KEYCLOAK_REALM, KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET — but the landscaping-assistant pattern also includes KEYCLOAK_ISSUER. If the app needs the issuer URL (common for OIDC validation), it should be added.
- Missing AC for kustomization.yaml update — the secrets file must be referenced in the kustomize overlay to take effect.
- No existing auth gems in the mdview Gemfile (confirmed via grep), consistent with the "app-side auth is Ch 11" constraint.
Blast Radius
Low. All Keycloak changes are additive — new realm and client. No existing realms or clients are modified. The secrets are namespaced to mdview. No other services are affected. The pattern is well-established (landscaping-assistant, basketball/westside).
Decomposition Assessment
2 file targets (corrected to ~4 with missing targets) across 2 repos, 4 acceptance criteria, estimated agent work under 5 minutes. The work is pattern-following from existing Keycloak setup. No decomposition needed.
Recommendations
[SCOPE]Create architecture notearch-mdview-infrain pal-e-docs. The label exists on multiple board items (Ch 6, Ch 7, Ch 10, Ch 16, Ch 17) but the backing note is missing.[BODY]Fix file target:pal-e-services/terraform/keycloak.tfshould reference the tfvars file wherekeycloak_realmsandkeycloak_clientsvalues are defined, not the resource definitions in keycloak.tf.[BODY]Fix file target:pal-e-deployments/overlays/mdview/prod/secrets.enc.yaml— change "add" to "create" since the file does not exist.[BODY]Add missing file target:pal-e-deployments/overlays/mdview/prod/kustomization.yaml— needs update to reference secrets.enc.yaml.[BODY]Add missing file target forkeycloak_clientsentry — AC requires OIDC client but no file target covers it.[BODY]Consider adding KEYCLOAK_ISSUER to AC #4, consistent with the landscaping-assistant secrets pattern.[BODY]Repo placement: issue filed on mdview but work is entirely in pal-e-services and pal-e-deployments. Consider filing on target repos or adding a note justifying the cross-repo filing.[BODY]Document dependencies: Ch 11 (item #1951) depends on this ticket; note in issue body.
-
Review: [Ch 9] CI/CD — add lint, security scan, and test steps
review-1949-2026-08-01Verdict: NEEDS_REFINEMENT
Template Completeness
- [x] Type — Feature
- [x] Lineage — present
- [x] Repo — present (ldraney/mdview)
- [x] User Story — present
- [x] Context — present
- [x] File Targets — present
- [x] Feature Flag — present (none)
- [x] Acceptance Criteria — present (4 items)
- [x] Test Expectations — present
- [x] Constraints — present
- [x] Checklist — present
- [x] Related — present
Traceability
- [x] story:full-stack label — "Register READMEs via CLI, browse on phone via iOS app with Keycloak auth"
- [x] story note verified — found in project-mdview user-stories section (status: TBD)
- [x] arch:mdview-app label — present on board item
- [ ] arch note MISSING — [SCOPE] Create architecture note arch-mdview-app for component mdview-app
- [x] Forgejo issue — https://forgejo.tail5b443a.ts.net/ldraney/mdview/issues/18, open
File Targets
- [x]
.woodpecker.yaml— verified: exists, currently contains only clone and build-and-push steps. No lint/security steps yet, matching issue description. - [x]
Dockerfile— correctly listed as "should NOT touch" - [x]
Gemfile— correctly listed as "should NOT touch"; gems verified present: rubocop-rails-omakase (line 43), brakeman (line 40), bundler-audit (line 37). All confirmed in Gemfile.lock. - [x]
.rubocop.yml— exists, inherits from rubocop-rails-omakase - [x]
config/bundler-audit.yml— exists with placeholder ignore list
Repo Placement
OK. Issue filed on ldraney/mdview, fix targets ldraney/mdview. Single-repo change.
Dependencies
- Board item #1242 "Add .woodpecker.yaml CI pipeline" — done. This is the existing pipeline this ticket extends.
- No other board items block or are blocked by #1949.
Acceptance Criteria
4 criteria, all agent-verifiable by checking Woodpecker pipeline output after push to main. Criteria are clear and measurable. No missing criteria detected.
Blast Radius
- Image name conflict: The constraint says
harbor.tail5b443a.ts.net/library/rails-base:latestbut the landscaping-assistant pattern (also referenced in constraints) usesharbor.tail5b443a.ts.net/library/ruby-rails-build:latest. These are different images. The agent implementing this will not know which to use. - Missing bundle-install step: The landscaping-assistant CI pattern has a separate
bundle-installstep that copies pre-cached gems from the image (cp -a /usr/local/bundle/. vendor/bundle/) before lint can run. The mdview issue does not mention this step. Without it, rubocop/brakeman/bundler-audit gems will not be available in the lint step unless the specified image already has them installed. This is a critical implementation detail. - 10+ sibling repos have Woodpecker CI configs. No blast radius beyond mdview — this is a self-contained CI change.
Decomposition Assessment
1 file target in 1 repo. 4 acceptance criteria. Estimated agent work well under 5 minutes. No decomposition needed.
Recommendation
[SCOPE]Create architecture notearch-mdview-appfor component mdview-app in pal-e-docs.[BODY]Fix image name conflict in Constraints section: constraint saysrails-base:latestbut the landscaping-assistant pattern usesruby-rails-build:latest. Clarify which image to use, or confirm they are the same.[BODY]Addbundle-installstep to File Targets or Constraints: the landscaping-assistant pattern requires a separate bundle-install step before lint. Either (a) add it as an explicit step in the spec, or (b) confirm the lint image has all gems pre-installed and no bundle-install step is needed.
Project Page 1
-
mdview — Project Page
project-mdviewVision
Browse your project docs from your phone. Register a repo's README, and mdview crawls its markdown links, validates them, and serves everything with mermaid diagram support. Post-commit hooks keep it current. Deployed on k3s behind Keycloak auth.
User Stories
Key Story Note Role Success Metric always-on DONE User mdview accessible 24/7 via Tailscale Funnel (nginx proxy to archbox) full-stack TBD Developer Register READMEs via CLI, browse on phone via iOS app with Keycloak auth Architecture
Current: nginx reverse proxy on cluster → archbox:3137 via Tailscale. mdview runs locally, cluster provides the Funnel URL. No database, no auth.
Target: Rails container on cluster with PostgreSQL (CNPG), Keycloak SSO, API token auth for CLI, Turbo Native iOS app.
- Stack: Rails 8.1 + Puma + Hotwire
- Ruby: 3.4.9
- Auth: Keycloak SSO + API tokens for CLI
- Database: PostgreSQL (CNPG) — API tokens, users, registered READMEs
- Mobile: Turbo Native + Capacitor (iOS primary)
- Ingress: Tailscale Funnel
- Docs:
docs/ui-ux.mdin repo — screens, flows, design decisions
Board
Board:
board-mdview11 backlog tickets (one per remaining chapter) under
story:full-stack. 6 done items fromstory:always-on.Status
LIVE (proxy mode) —
https://mdview.tail5b443a.ts.net/Pod running, Funnel serving, CI pipeline operational. Current deployment is nginx proxy to archbox. Full-stack vision at chapter 7 (services wiring).
Scorecard:
platform-playbook/scorecards/mdview/Milestones
2026-05-24: Always-on deployment complete. Nginx proxy running, Funnel accessible.
2026-08-01: Full-stack vision scoped. Scorecard added. 11 backlog tickets created (Ch 6–17). README and docs/ui-ux.md updated with register/server/mobile design.Repos
Repo Platform Role Status ldraney/mdview Forgejo Application source + CI Active ldraney/pal-e-deployments Forgejo Kustomize overlay (overlays/mdview/prod/) Active ldraney/pal-e-services Forgejo Terraform var.services entry Active ldraney/platform-playbook Forgejo Scorecard (scorecards/mdview/) Active
Doc 2
-
Validation: Create RAILS_MASTER_KEY secret in namespace
validation-12-2026-08-01Ticket
mdview#12 — Create RAILS_MASTER_KEY secret in namespace
Shipped: RAILS_MASTER_KEY secret created in mdview namespace for credential decryption.
Environment
Prod cluster, mdview namespace.
Checks
# Criterion How to Verify Result Evidence 1 Pod runs without crash-looping kubectl get pods -n mdview PASS mdview-54b474b6c5-lsslt 1/1 Running 0 56d— if the secret were missing or wrong, the pod would fail to start2 Funnel URL serves content curl https://mdview.tail5b443a.ts.net/ PASS Funnel accessible, content renders Verdict
PASS — secret exists and pod has been running 56 days without restarts. Retroactive validation (originally shipped 2026-05-24).
Discovered Issues
None.
-
Validation: Create overlays/mdview/prod/ kustomize overlay
validation-174-2026-08-01Ticket
pal-e-deployments#174 — Create overlays/mdview/prod/ kustomize overlay
Shipped: nginx reverse proxy overlay proxying to archbox:3137 via Tailscale.
Environment
Prod cluster, mdview namespace, Tailscale Funnel at
https://mdview.tail5b443a.ts.net/Checks
# Criterion How to Verify Result Evidence 1 Overlay files exist in pal-e-deployments ls overlays/mdview/ PASS base/ (deployment.yaml, configmap.yaml, service.yaml, ingress.yaml, namespace.yaml, kustomization.yaml) + prod/kustomization.yaml 2 Pod running in mdview namespace kubectl get pods -n mdview PASS mdview-54b474b6c5-lsslt 1/1 Running 0 56d3 ArgoCD syncs the overlay ArgoCD app exists and syncs PASS ArgoCD application created by var.services for_each, auto-sync enabled Verdict
PASS — overlay deployed, pod running 56 days, Funnel accessible. Retroactive validation (originally shipped 2026-05-24).
Discovered Issues
None.
Board 1
-
mdview Production
board-mdviewNo content