fix(guide): default served-audiences to customer — fail safe, not fail open
CD - Develop (guide → bcos.dev) / build-and-deploy (push) Successful in 2m18s
CD - Develop (guide → bcos.dev) / build-and-deploy (push) Successful in 2m18s
The environment cap decided what a Guide instance serves, but defaulted to ALL four tiers. That makes the safe configuration the one you have to remember: a missing or misspelled GUIDE_SERVED_AUDIENCES in production would serve 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 was all it took. Default is now `customer`. Environments opt UP explicitly: production -> unset (customer only: modules + Customer tab) bcos.dev/DLX -> customer,internal,dev,bcos (set in that instance's compose) bcos.dev's compose was pinned to all four tiers first (hiveiq-openmetal-dev b2d4e00, already live on .251) so this change cannot narrow it. Also updates platform.guide-access, which documented the old default and told readers the opposite of what the code now does. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -5,8 +5,9 @@ name: CD - Develop (guide → bcos.dev)
|
||||
# not enough. This automates that on every push to develop: build → push :dev → deploy to bcos.dev.
|
||||
#
|
||||
# Auto-deploy is intentional and scoped to the DEV environment only (docs, low blast radius).
|
||||
# Audience filtering is runtime (GUIDE_SERVED_AUDIENCES): bcos.dev serves all four tiers; prod
|
||||
# (a future cd-main, gated) serves only customer,internal — so dev/bcos content never leaves dev.
|
||||
# Audience filtering is runtime (GUIDE_SERVED_AUDIENCES). The app default is `customer` (fail-safe);
|
||||
# bcos.dev opts UP to all four tiers explicitly in its compose. Production leaves it unset and so
|
||||
# serves customer only — internal/dev/bcos content never leaves dev, even if a config line is missed.
|
||||
|
||||
# Auto-deploy live: BCOS_DEV_DEPLOY_KEY provisioned (scoped forced-command key on .251).
|
||||
|
||||
|
||||
@@ -23,9 +23,18 @@ internal.secret=${INTERNAL_SECRET:dev-internal-secret}
|
||||
|
||||
cors.allowed-origins=${CORS_ALLOWED_ORIGINS:http://localhost:5188}
|
||||
|
||||
# Audience tiers this instance serves (per-environment cap).
|
||||
# bcos.dev / DLX = all four; production = customer,internal (dev/bcos never leave dev).
|
||||
guide.served-audiences=${GUIDE_SERVED_AUDIENCES:customer,internal,dev,bcos}
|
||||
# Audience tiers this instance serves (per-environment cap), checked BEFORE any role
|
||||
# gating — a tier that is not served never leaves the process, whatever the caller's role.
|
||||
#
|
||||
# The default is deliberately the SAFEST tier, not the fullest: a missing or misspelled
|
||||
# GUIDE_SERVED_AUDIENCES must never be the reason internal content reaches a customer.
|
||||
# MSP_ADMIN is a customer-facing role (QDS log in as MSP_ADMIN), so a fail-open default
|
||||
# would expose the Architect/Claude tiers to customers on one forgotten env line.
|
||||
#
|
||||
# Each environment opts UP explicitly:
|
||||
# production -> customer (leave unset; the default is correct)
|
||||
# bcos.dev/DLX -> customer,internal,dev,bcos (set in that instance's compose)
|
||||
guide.served-audiences=${GUIDE_SERVED_AUDIENCES:customer}
|
||||
|
||||
# In-guide feedback → Gitea issues (server-side token; reaches Gitea via public route)
|
||||
gitea.base-url=${GITEA_BASE_URL:https://hiveiq-gitea.directlx.dev}
|
||||
|
||||
@@ -92,6 +92,22 @@ not document itself apart from this page.
|
||||
## Environment cap
|
||||
|
||||
`guide.served-audiences` (env `GUIDE_SERVED_AUDIENCES`, `application.properties`) caps which tiers
|
||||
an instance serves at all, *before* the role check. It currently defaults to **all four tiers**
|
||||
(`customer,internal,dev,bcos`). If the Guide is ever deployed to production, set this explicitly —
|
||||
the default serves everything.
|
||||
an instance serves at all, *before* the role check. A tier that is not served never leaves the
|
||||
process — role gating can only narrow the result further, never widen it past the cap.
|
||||
|
||||
The default is **`customer`** — the safest tier, not the fullest. Each environment opts *up*
|
||||
explicitly:
|
||||
|
||||
| Environment | `GUIDE_SERVED_AUDIENCES` | Serves |
|
||||
|---|---|---|
|
||||
| **Production** | *(unset — default)* | `customer` only: modules + the Customer tab |
|
||||
| **bcos.dev / DLX** | `customer,internal,dev,bcos` | all four tiers |
|
||||
|
||||
**Why the default is the strict one:** MSP_ADMIN is a customer-facing role (QDS log in as
|
||||
MSP_ADMIN), so a fail-open default would mean one forgotten env line exposes the Architect and
|
||||
Claude tiers to a customer. The safe case has to be the lazy case. bcos.dev carries the permissive
|
||||
value explicitly in its compose.
|
||||
|
||||
**Note:** the cap governs what is *served*, not what is *present*. All content ships inside the
|
||||
image regardless of tier, so it is readable by anyone with registry access or a shell in the
|
||||
container. The cap is a serving boundary, not an at-rest one.
|
||||
|
||||
Reference in New Issue
Block a user