Skip to content

map view: a deployment-wide default map style (setting + runtime-config + Console CSP), so an intranet deployment can replace demotiles.maplibre.org #26001

Closed

Description

@objectstack-fleet

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.tsx reads schema.mapStyle || schema.map?.style; spec ui/component.zod.ts (mapStyle) and ui/view.zod.ts (ListMapConfigSchema.style). No deployment-level source exists.
  • ui/packages/plugin-map/src/ObjectMap.tsx DEFAULT_MAP_STYLE is the demotiles URL, used as the fallback.
  • No env/vite/runtime-config read in plugin-map; plugin-map does not depend on app-shell, so it cannot call getRuntimeConfig() 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 in connect-src, computed once at boot; OS_CONSOLE_CSP_CONNECT_SRC is 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)

  1. Home of the value: a Setup setting served via runtime-config (the card's ask) or an env var read by RuntimeConfigPlugin.
  2. 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.
  3. 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

  1. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    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.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    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:

    • Read on origin/main: packages/cli/src/utils/console.ts:724 DEFAULT_MAP_STYLE_ORIGIN = 'https://demotiles.maplibre.org'; :695 OS_CONSOLE_CSP_CONNECT_SRC is the existing operator-only way to widen connect-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).
    • ADR-0026 already decides that a distributed UI plugin's network hosts are declared as permissions.network → per-plugin CSP connect-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 (control OS_CONSOLE_CSP_CONNECT_SRC → hits in console.ts); no ADR names a map style default.
    • Half-state read, not written: needs-user-decision + pm:awaiting-maintainer together (6412086679); the second leaves in the ruling's stroke.
    • Facets block (the card carried none):

    os-decision-facets

  3. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    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 as OS_{DOMAIN}_{NAME} — the dev proposes the name, e.g. OS_CONSOLE_MAP_STYLE_URL) read by RuntimeConfigPlugin (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 CSP connect-src at boot the way OS_CONSOLE_CSP_CONNECT_SRC already is (packages/cli/src/utils/console.ts:695, :724 holds 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 widen connect-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-map seam that reads the runtime-config value as the fallback before the demotiles URL; domain:ui sub-card beside #25889 item 1).

    Execution: needs-user-decision → pm:queue in this act (domain:server, p2, area:records); pm:awaiting-maintainer removed in the same stroke (half-state beside the decision label). The server card lands first; the holding domain:server seat files the domain:ui sub-card for the renderer seam with Blocked-by: this card. Ruling-ref: names this comment; Clause-②: no, Metadata-protocol: none (an env var and a runtime-config field, no authorable key).

  4. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 8 · card thread
    Session: session_01R1q2xdtYgU6FKrZ7LgjPCC (the seat); the card thread is session_011ApYCfy4gzYfuYeXX38EcT
    Account: 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:server
    Seat: domain:server#1
    Ruling-ref: 6413991421 (letter A, maintainer 2026-10-26T10:38Z): one operator env (name per AGENTS.md Prime Directive #9) read by RuntimeConfigPlugin and served as the deployment's default map style, and added to the Console CSP connect-src at boot; no Setup setting, no settings key, no spec key, no per-request CSP
    File surface: packages/cloud-connection/src/runtime-config-plugin.ts, packages/cli/src/utils/console.ts, their tests, the deployment/env reference doc that lists OS_CONSOLE_CSP_CONNECT_SRC (if one exists), one changeset. ⛔ No ui/** (the plugin-map seam is the domain:ui sub-card this seat files with Blocked-by: #26001), ⛔ no packages/spec/**, ⛔ no docs/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/main 679fc7ce87: card open, unassigned, pm:queue, no claim; console.ts holds DEFAULT_MAP_STYLE_ORIGIN and OS_CONSOLE_CSP_CONNECT_SRC; the runtime-config payload has no map key)
    Serial constraints cleared: open PRs touching runtime-config-plugin.ts or console.ts: none. The dev re-measures before pr_create.

  5. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    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

  6. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed

    PR #26162 merged at 2026-10-26T14:58Z by the merge queue as 21075ce614 on main (Fixes #26001; ACCEPT 6418646086).

    Reading Probe Result
    Queue membership git ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-26162-*' 0 refs
    origin/main by content git cat-file -e origin/main:packages/cloud-connection/src/console-map-style.ts present
    Ancestry git merge-base --is-ancestor 21075ce614 origin/main holds

    State: this card closed by Fixes (completed); pm:dispatched removed. Follow-ups: domain:ui sub-card #26163 (plugin-map reads mapStyleUrl; its Blocked-by: #26001 clears with this close) and cloud-lane card #26164 (status:parked).


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p2Medium: important, M3security

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions