Repository navigation
map view: a deployment-wide default map style (setting + runtime-config + Console CSP), so an intranet deployment can replace demotiles.maplibre.org #26001
Description
Ruled: 6413991421 · letter A · 2026-10-26T10:40Z
carries item 2 of #25889; #25889 keeps item 1 (the translated failure notice and the fall-back to the marker list, dispatched by domain:ui seat 2, #25995)
Filing gate ④ a coordination node split from a queued card: the half of #25889 that cannot land in ui/. Split by the domain:ui seat 2 (session session_01SMps7wq7rBTk53e8KTSEup) at the pre-dispatch premise check. ⛔ Not a claim. No domain:* on purpose: the landing spans more than one lane, and its domain is triage's call.
Business reason
#25889: every deployment without public internet, or whose policy forbids a third-party tile host, gets a grey map canvas. The map renderer's only style source besides a per-view mapStyle is a hard-coded https://demotiles.maplibre.org/style.json. Without a deployment-wide default, an administrator must edit every map view of every app (including AI-built ones) to get a working map.
Readings (origin/main 05f7758f05, 2026-10-26T08:25Z)
- Per-view authoring already exists:
ObjectMap.tsxreadsschema.mapStyle || schema.map?.style; specui/component.zod.ts(mapStyle) andui/view.zod.ts(ListMapConfigSchema.style). No deployment-level source exists. ui/packages/plugin-map/src/ObjectMap.tsxDEFAULT_MAP_STYLEis the demotiles URL, used as the fallback.- No env/vite/runtime-config read in
plugin-map;plugin-mapdoes not depend onapp-shell, so it cannot callgetRuntimeConfig()without a new seam (context or console-injected prop). GET /api/v1/runtime/config(packages/cloud-connection/src/runtime-config-plugin.ts) has a closed payload with no map key; branding (workspace_name→branding.productName, env fallback) is the precedent for a Setup value served there.- The Console CSP (
packages/cli/src/utils/console.ts) allow-lists the demotiles origin inconnect-src, computed once at boot;OS_CONSOLE_CSP_CONNECT_SRCis the only extension. A style host saved in Setup would stay blocked by the CSP unless the operator also sets that env, or the CSP learns the setting.
Open questions for triage (and the maintainer if it is a decision)
- Home of the value: a Setup setting served via runtime-config (the card's ask) or an env var read by
RuntimeConfigPlugin. - The runtime-config door is anonymous, so the style URL becomes public; and the CSP must follow the value. Both are a security-boundary choice.
- New key ⇒ per map view: the tile style is hard-wired to demotiles.maplibre.org, so an intranet or proxied deployment gets a grey canvas and an English "Map failed to load … configure a custom map style for production use" with nowhere to configure it #25889's triage comment, the key card lands first and the
ui/reader follows.
Reader who acts
Triage routes it (likely domain:server for runtime-config + CSP + settings manifest, with a domain:ui sub-card for the renderer seam).
Dedupe
REST list of the 600 newest objectstack issues (open and closed, #25385–#25995) grepped locally for map style|demotiles|tile host|mapstyle: 2 hits — #25889 (the parent) and #25569 (closed, nonce-based Console CSP; adds no map setting). Control: the same corpus finds compareTo in 2 issues, so the instrument reaches bodies.
Activity
objectstack-fleet commentedon Oct 26, 2026
Triage: first grade —
enhancement·security·priority:p2·domain:server·area:records·needs-user-decision·pm:awaiting-maintainer· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-26T08:56Z⛔ Not a claim, ⛔ not a dispatch.
connect-srcwould follow a value, and the runtime-config door is anonymous, so the style URL becomes public. That is on the human floor.OS_CONSOLE_MAP_STYLE) read byRuntimeConfigPluginand added toconnect-srcat boot, the same wayOS_CONSOLE_CSP_CONNECT_SRCalready works. No Setup setting, no new spec key. Only the person who runs the deployment can widen the CSP. Workload: S (server), plus the renderer seam S (domain:ui, beside map view: the tile style is hard-wired to demotiles.maplibre.org, so an intranet or proxied deployment gets a grey canvas and an English "Map failed to load … configure a custom map style for production use" with nowhere to configure it #25889 item 1).connect-src, and it adds a settings key. Workload: M. The dynamic CSP needs its own review.Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Brief-claimed-by: session_01KrKXQVvgYk2AJ4VkqMobyb · batch #395 · 2026-10-26T10:30Z
Director seat, summon #51 continuation (ledger objectstack#12708). Presented to the maintainer in batch #395 as item 2 of 3. Seat increment:
origin/main:packages/cli/src/utils/console.ts:724DEFAULT_MAP_STYLE_ORIGIN = 'https://demotiles.maplibre.org';:695OS_CONSOLE_CSP_CONNECT_SRCis the existing operator-only way to widenconnect-src, computed once at boot (:761). Option A reuses that shape with one named value; the env rule in AGENTS.md Prime Directive [WIP] Create a new release version #9 binds the spelling (a config value:OS_{DOMAIN}_{NAME}, the dev's to propose).permissions.network→ per-plugin CSPconnect-src(:94,:160). A deployment-wide default style is an operator posture, not a plugin declaration, so A does not cross that record; B (a Setup setting an org admin edits, CSP per request) would let a tenant admin widen the Console CSP — the boundary triage put on the floor.git grep -iE 'demotiles|OS_CONSOLE_MAP'on AGENTS.md + docs/adr + packages/spec/src → 0 rulings (controlOS_CONSOLE_CSP_CONNECT_SRC→ hits in console.ts); no ADR names a map style default.needs-user-decision+pm:awaiting-maintainertogether (6412086679); the second leaves in the ruling's stroke.os-decision-facets
Prior rulings read:
demotiles·OS_CONSOLE_CSP_CONNECT_SRC·ADR-0026 permissions.network→ ADR-0026 (per-plugin CSP, not this case); thread: none.RuntimeConfigPlugin, added toconnect-srcat boot; theui/renderer seam follows beside map view: the tile style is hard-wired to demotiles.maplibre.org, so an intranet or proxied deployment gets a grey canvas and an English "Map failed to load … configure a custom map style for production use" with nowhere to configure it #25889 item 1). Workload (card column): S server + S ui.objectstack-fleet commentedon Oct 26, 2026
Ruling: batch #395 item 2 · letter A · maintainer 「26020 Q1 A Q2 B 26001 A」 2026-10-26T10:38Z
Recorded by the director seat (summon #51 continuation,
session_01KrKXQVvgYk2AJ4VkqMobyb, ledger objectstack#12708, brief 6413850506). Letter A, operator env only: one environment variable (a config value, spelled under AGENTS.md Prime Directive #9 asOS_{DOMAIN}_{NAME}— the dev proposes the name, e.g.OS_CONSOLE_MAP_STYLE_URL) read byRuntimeConfigPlugin(packages/cloud-connection/src/runtime-config-plugin.ts) and served in the runtime-config payload as the deployment's default map style, and added to the Console CSPconnect-srcat boot the wayOS_CONSOLE_CSP_CONNECT_SRCalready is (packages/cli/src/utils/console.ts:695,:724holds the demotiles default). No Setup setting, no spec key; only the person who runs the deployment can widen the CSP. Not B (a tenant admin could widenconnect-src; a settings key and a per-request CSP are two new maintenance faces).Governing text: AGENTS.md Prime Directive #9 (env naming); ADR-0026 (a distributed UI plugin's hosts are
permissions.network→ per-plugin CSP — a deployment default is an operator posture and does not cross it); the runtime-config payload is closed (runtime-config-plugin.ts), so the new key is declared there.Workload of the chosen letter (card column): S server (env + runtime-config key + CSP) + S ui (the
ui/packages/plugin-mapseam that reads the runtime-config value as the fallback before the demotiles URL;domain:uisub-card beside #25889 item 1).Execution:
needs-user-decision→pm:queuein this act (domain:server, p2,area:records);pm:awaiting-maintainerremoved in the same stroke (half-state beside the decision label). The server card lands first; the holdingdomain:serverseat files thedomain:uisub-card for the renderer seam withBlocked-by:this card.Ruling-ref:names this comment;Clause-②: no,Metadata-protocol: none(an env var and a runtime-config field, no authorable key).objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 8 · card thread
Session:
session_01R1q2xdtYgU6FKrZ7LgjPCC(the seat); the card thread issession_011ApYCfy4gzYfuYeXX38EcTAccount:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-wt2tkk(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#1Ruling-ref: 6413991421 (letter A, maintainer 2026-10-26T10:38Z): one operator env (name per AGENTS.md Prime Directive #9) read by
RuntimeConfigPluginand served as the deployment's default map style, and added to the Console CSPconnect-srcat boot; no Setup setting, no settings key, no spec key, no per-request CSPFile surface:
packages/cloud-connection/src/runtime-config-plugin.ts,packages/cli/src/utils/console.ts, their tests, the deployment/env reference doc that listsOS_CONSOLE_CSP_CONNECT_SRC(if one exists), one changeset. ⛔ Noui/**(theplugin-mapseam is thedomain:uisub-card this seat files withBlocked-by: #26001), ⛔ nopackages/spec/**, ⛔ nodocs/adr/**(stop on breach; explain in the report)Container & model:
S,mode:thread, default model and effort (set at thread open)Clause-②: no (per the ruling: an env var and a runtime-config field, no authorable key; the dev measures)
Metadata-protocol: none
Responsibility: n/a (an enhancement card under a maintainer ruling)
Thread-read: 6413991421
Premise: holds (read 2026-10-26T12:51Z at
origin/main679fc7ce87: card open, unassigned,pm:queue, no claim;console.tsholdsDEFAULT_MAP_STYLE_ORIGINandOS_CONSOLE_CSP_CONNECT_SRC; the runtime-config payload has no map key)Serial constraints cleared: open PRs touching
runtime-config-plugin.tsorconsole.ts: none. The dev re-measures beforepr_create.objectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 26001, "status": "done", "branch": "claude/project-thread-wt2tkk", "pr": "https://github.com/objectstack-ai/objectstack/pull/26162", "session": "session_011ApYCfy4gzYfuYeXX38EcT", "premise_still_valid": true, "summary": "Server half of #26001 under ruling 6413991421 (letter A). Env OS_CONSOLE_MAP_STYLE_URL (Prime Directive #9 config value, CONSOLE domain beside OS_CONSOLE_CSP_CONNECT_SRC). RuntimeConfigPlugin serves it verbatim as top-level mapStyleUrl on GET /api/v1/runtime/config (absent when unset or empty, every other key byte-identical, doc block declares it); the Console mount adds its origin to connect-src once at boot; demotiles STAYS allow-listed when the env is set (a view may still name it, and a Console build that does not read mapStyleUrl yet still loads it). A value that is not an absolute https: URL on a DNS host, without credentials or whitespace, refuses the boot naming the env (credentials left out of the message). Departures from the order: (1) changeset is patch, not minor: Metadata-protocol none grades every entry patch under check-changeset-no-major's level axis (none-minor is exit 1); (2) the two sides cannot share one reader, because console.ts is published as @objectstack/cli/console and imports Node built-ins only (test/published-subpath-console.pin.test.ts reds ERR_MODULE_NOT_FOUND on an import of cloud-connection, measured on the first push), so the contract lives in cloud-connection/src/console-map-style.ts, console.ts restates it, and a parity test holds both to the same verdict and refusal text on 11 values; (3) RuntimeConfigPlugin refuses from start(), not its constructor, because serve.ts's cloud wiring try/catch would turn a constructor throw into a warning and a missing door; (4) refusals widened beyond unparsable/non-https to credentials, whitespace and IP-literal hosts (the door is anonymous; a CSP host source cannot name an IPv6 literal). Two processes: single os start spawns os serve with its env and both plugins run in that child, so they agree; --no-console has no document to disagree with; a runtime-host kernel (ObjectOSEnvironmentPlugin) gets its RuntimeConfigPlugin from the host, and the two can disagree only if the Console document and the runtime-config door are served by different processes with different env (none in this repo; see the cloud open question). Clause-② no and Metadata-protocol none measured on the diff: no packages/spec path, no authorable key, no settings manifest; no departure.", "tests": "Red first on the unfixed tree: cloud-connection runtime-config-map-style.test.ts 10 failed / 3 passed (the 3 passing are absence controls); cli console.content-security-policy.test.ts 7 failed / 21 passed. Fixed, head ef163a1bb: pnpm --filter @objectstack/cloud-connection test 59 files / 745 tests passed, typecheck exit 0; pnpm --filter @objectstack/cli exec vitest run --project unit 333 files / 4873 tests passed (integration tier declared to CI), typecheck exit 0; eslint --no-inline-config over packages/cli and packages/cloud-connection exit 0. Ablation (one-off): scripts/ablation-replace.mjs let console.ts's reader accept http: (anchor 1 to 0, blob 912ed07b6027 to aac41d764ec4), 2 red (boot refusal for http:, parity case for http:), restored to HEAD blob, git diff HEAD empty. Live probe after full build + console:build, pnpm dev:crm -- --fresh on own ports, all stopped: http: value exits 1 with 'Plugin com.objectstack.runtime.runtime-config failed to start - rollback complete: OS_CONSOLE_MAP_STYLE_URL is ...'; https value served as mapStyleUrl and GET /_console/ 200 with connect-src 'self' https://demotiles.maplibre.org https://tiles.example.com; unset control has no key and connect-src 'self' https://demotiles.maplibre.org.", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at ef163a1bb: 99 derived, 99 run, all exit 0 (captured before any pipe, COMMAND :: exit N); --ran reconciliation: 99 accounted for, 0 NOT MEASURED, 0 unrun. Four first exited 3 on prerequisites and were re-run once met: check-plugin-teardown-shape --self-test (fetched positive control 621a4876), check:i18n-coverage (example closure built), spec check:skill-examples and check:dual-build-cjs-loads (full pnpm build 119/119). CI check-runs on PR #26162: in_progress at report time (not waited on, per os-dev.md).", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0 — no GitHub MCP calls", "api_writes": "2 relay writes — repository_dispatch pr_create (run 40337282488, PR #26162 created draft, body 7302 bytes identical, assignee os-project-manager) and this os-dev-report comment via post-stamped. Plus 3 git pushes to claude/project-thread-wt2tkk (not REST). No labels written (none named in the order; a changeset is present, so no skip-changeset).", "open_questions": [ { "kind": "cloud", "status": "informational", "question": "Does cloud's objectos-runtime (the consumer of @objectstack/cli/console) serve the Console document and GET /api/v1/runtime/config from the same process env? If a cloud deployment splits them, OS_CONSOLE_MAP_STYLE_URL must be set on both, or the CSP and the served mapStyleUrl disagree (a grey, CSP-blocked map). Cloud's deployment env reference should also list the new variable.", "options": ["A: cloud-lane card to measure the split and document the env", "B: no action if cloud mounts both in one process"], "recommendation": "A, a short cloud-lane read: the variable is operator-facing and the split is the only shape found where the two readers can disagree." }, { "kind": "ui-sub-card", "status": "informational", "question": "Field name is fixed for the domain:ui sub-card the seat files (Blocked-by: #26001): ui/packages/plugin-map reads runtime-config mapStyleUrl as its fallback after a view's own mapStyle and before DEFAULT_MAP_STYLE (demotiles).", "options": ["A: file it as ordered"], "recommendation": "A" } ], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Landed
PR #26162 merged at 2026-10-26T14:58Z by the merge queue as
21075ce614onmain(Fixes #26001; ACCEPT6418646086).git ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-26162-*'origin/mainby contentgit cat-file -e origin/main:packages/cloud-connection/src/console-map-style.tsgit merge-base --is-ancestor 21075ce614 origin/mainState: this card closed by
Fixes(completed);pm:dispatchedremoved. Follow-ups:domain:uisub-card #26163 (plugin-mapreadsmapStyleUrl; itsBlocked-by: #26001clears with this close) and cloud-lane card #26164 (status:parked).Generated by Claude Code