release(guide): develop -> main — markdown Guide + audience cap, for production deploy #27
Reference in New Issue
Block a user
Delete Branch "develop"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Release
develop->mainso the Guide can be deployed to production.Why now
mainis not an older Guide — it is a different application. It predates the markdown rewrite and, if built, would produce an empty and uncapped Guide:main(59fce91, 2026-06-29)develop/api/v1/guides/{pageKey}/api/v1/guide/nav,/api/v1/guide/modules/{module}guide.served-audiencesUntil this lands, anyone building hiveops-guide from
main— includingcd-mainif it ever starts running — gets an empty Guide with no audience gating at all. That is the main risk this PR retires.Security: the cap now fails safe (
451c475)The environment cap decided what an instance serves, but defaulted to all four tiers. That made the safe configuration the one you had to remember — a missing or misspelled
GUIDE_SERVED_AUDIENCESin production would have served the Architect and Claude tiers to any MSP_ADMIN, and MSP_ADMIN is a customer-facing role (QDS log in as MSP_ADMIN). One forgotten env line, same class as the feedback import that exposed internal Security tickets to QDS.Default is now
customer. Environments opt UP explicitly:GUIDE_SERVED_AUDIENCEScustomer: modules + Customer tab (68 of 426 docs)customer,internal,dev,bcosbcos.dev was pinned to all four tiers first (
hiveiq-openmetal-devb2d4e00, already live on.251) so this cannot narrow it.platform.guide-accessis updated too — it documented the old default and told readers the opposite of what the code now does.Verified in code: the cap is checked in
visible()before any role logic, on both read paths (nav()andmodule()). Role can narrow the set, never widen it past the cap. Caveat recorded in the docs: the cap governs what is served, not what is present — all content still ships in the image.What is in it
84 commits, 2026-06-30 -> 2026-07-16:
hiveiq_guideDB is a fossil of the old design and is unused).guide.served-audiences(customer < internal < dev < bcos), enforced server-side inMarkdownGuideService.f21c783— gate Architect + Claude tabs to BCOS_ADMIN only (#16)4f84fc5— dev tier BCOS_ADMIN-only; keep Testing for MSP (#18)7174229bump hiveops-bom 1.0.5 -> 1.0.7, clears httpcore5 + postgresql CVEs.e1fcd4cSlack notify made non-fatal.Notes for the reviewer
cd-develop.yml; there is nocd-main, so this merges on approval alone with no automated check (devops#46).4.0.0->1.0.0. The rewrite reset the lineage. Harmless whilebuild.shtags:latest, but worth a conscious nod.-SNAPSHOTin the pom.Known follow-up — not fixed here
GuidePanel.sveltein hiveops-incident still calls the OLD contract (/guide/api/v1/guides/{pageKey}, keysincidents.list/incidents.create). That is the root cause of feedback #788 ("Guide button not working for MSP") — an unmigrated consumer, not a typo. It needs repointing to/guide/api/v1/guide/modules/{module}withincident.*keys. The Guide button stays dead until that lands, deploy or no deploy.🤖 Generated with Claude Code
Phase 1 of the guide rebuild (DESIGN.md): - MarkdownGuideService scans content/**/*.md (frontmatter: module/title/tab/order/audience) - GET /api/v1/guide/nav + /api/v1/guide/modules/{module}; audience gated by role (internal tabs only for MSP_ADMIN/BCOS_ADMIN) - Removed JPA/Flyway/Postgres, Guide entity/repo/service, admin CRUD, seed migrations - Seed content: devices.sw-deploy (Overview/Data/Technical-internal), fleet.tasks - Verified: boots with no DB, loads 4 docs, nav + audience filtering + 401 all correct Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>New GuideReader.svelte: nav tree (apps→modules) + tabbed markdown (marked), audience-gated server-side (admins see internal tabs, badged). Replaces the old DB-CRUD GuidesView. Consumes GET /api/v1/guide/nav + /modules/{module}. Deployed to guide.bcos.dev. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Document the MSP_MANAGED/CUSTOMER_MANAGED incident ownership mode across the Claude/Internal/Architect/Testing/Customer tabs: the write matrix, the /institution-keys/{key}/incident-mode endpoint + MSP toggle, controller-layer assertWritable enforcement, IncidentDTO.institution, V90 migration, and the known UI follow-up (customer nav still hidden). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>The Notify Slack step could fail the whole job (turning a successful deploy red, as just happened). A notification must never fail a deploy: - continue-on-error: true on the step - curl captures HTTP code and never propagates a non-zero exit (|| echo) - logs "slack notify HTTP: <code>" so we can see if the runner reaches Slack - first commit line via ${VAR%%$'\n'*} param-expansion (no head pipe) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>incident.journal-events (Claude tab): the state flip is a dual-write — incident writes its own atm_properties, then mirrors to devices, and it is devices the UI reads. Adds the best-effort/afterCommit semantics and the nginx-listener URL rule. technical.devices: document POST /api/internal/atms/{agentAtmId}/service-state, that devices does not ingest journal events, the now()-stamped supervisor_entered_at, and that the status badge is derived client-side (agent-offline masks IN_SUPERVISOR). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Two new BCOS-only modules documenting the two environments and the rule that separates them: devops.prod Production Environment (OpenMetal) — hosts, repo layout, health report + config drift, and the KNOWN DRIFT warning: main's 00-backends.conf names different active blue/green slots than prod actually serves (devices/transactions/agent-proxy), so deploying it as-is flips three services to the wrong slot. Do NOT bulk-copy main over prod. devops.dev Dev Environment (bcos.dev) — single 16G all-in-one VM at ~93-97% RAM (recreate JVM services ONE at a time), its own postgres and registry, the new 06:00 health report (johannes only), and the health-check gotchas that must not be "fixed" back: SPA frontends return 200 for /actuator/health so the body must be checked, the probe must retry, and exited *-green/*-blue are standby slots. Both audience: bcos. The rule, now stated in both: everything bcos.dev -> hiveiq-openmetal-dev everything prod -> hiveiq-openmetal-prod shared, env-agnostic -> hiveiq-devops Also corrects devops.backups and devops.security, which still told readers the backup/security scripts live in `hiveops-devops/scripts/ops/`. They were moved to `hiveiq-openmetal-prod/scripts/ops/` today — the Guide is the source of truth, so a stale path in it is worse than none. Refs: hiveiq-ops/hiveiq-devops#39, #38 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>platform.deployment and processes.release both walked the reader through ./build.sh, never mentioning that cd-develop/cd-main already build and scan. Following either one produces an UNSCANNED image that races CI for the mutable :dev tag. That is what happened on 2026-07-13: a full day of hand-built images reached bcos.dev without passing Trivy. Verified against the workflow YAML and both runners on 2026-07-14: - cd-develop does NOT deploy for 6 of 8 repos. Only incident and devices deploy to bcos.dev; everywhere else CI stops at push. The old 'a green run redeploys the service' claim was wrong. - hiveops-fleet CI builds the FRONTEND ONLY — the fleet backend is built by neither cd-develop nor cd-main. hiveops-devices cd-main builds only the frontend too. Flagged as defects. - runner-02 IS active (incident built on it today) — the 'not the active worker' note was wrong. - CI now pushes an immutable :<sha8> alongside :dev/:latest, so deploys can pin a scanned image. Also records the runner failure signatures ('lease does not exist', 'network ... not found'), the daemon-restart + prune runbook, the standing warning never to garbage-collect or delete /opt/docker-registry, and the fact that merging a batch of PRs at once overwhelms a runner's 4 shared job slots and breaks its Docker daemon. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Update the msp.institution-keys module (Customer/Internal/Claude/Testing tabs) and technical.devices to match the new authz: - Only BCOS_ADMIN can create/delete institution keys; MSP admins edit only and must submit a request to BCOS to add/remove an institution. - POST/DELETE /api/institution-keys -> hasRole('BCOS_ADMIN'); PUT stays MSP+BCOS. - Note the underlying ownership gap (devices mints institutions with no mgmt mirror; keys have diverged) tracked in msp#29. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>The Task Permissions tab shipped in hiveops-fleet#119 and is live, but had no guide module at all — the API returned 404 for fleet.task-permissions, and fleet.tasks mentions permissions once without describing the grant model. This is the setting that decides which commands a customer may push to their own ATMs: deny-by-default, per-institution, per-command. Highest-consequence fleet setting we have, least documented. Adds the 5 canonical role tabs, grounded in hiveops-fleet source: - Customer — grant/revoke, why only Reboot + Restart Agent are offered - Internal — triage for "customer cannot reboot", what we never widen - Architect — deny-by-default rationale, the two independent gates, replace-not- merge semantics, why GRANTABLE lives in code - Testing — role matrix + the 400-on-CONFIG_UPDATE case, against bcos.dev - Claude — ownership, table, endpoints, gotchas Verified: all 5 tabs parse under MarkdownGuideService.parse(); reconciler counts 126 modules with no missing role-tabs. Role matrix confirmed live on bcos.dev (CUSTOMER 403/403/200/403, MSP_ADMIN 200/200/200/200). Refs #23. Follow-up to hiveops-fleet#119, hiveops-fleet#100. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>customer— fail safe, not fail open