sgit newsroom v0.1.29 · snapshot 2026-09-24

Reading room · riskmandate.ai

On this page

Reading room / riskmandate.ai · raw text · live ↗

From riskmandate.ai, the page as fetched on 2026-09-25 · open the live page ↗Everything on this sheet is the source site's own text; the newsroom's chrome is outside it.

Implementation Brief — Scenarios pilot (first decoupled content area)

Rendered from docs/briefs/implementation__scenarios-pilot.md in the repository. The text below is that file. Source: https://riskmandate.ai/admin/briefs/implementation__scenarios-pilot/↗ · noindex · written by scripts/site/build-admin.mjs

Status: IN BUILD — vault dm42qcaw provisioned (seeded by the vault team with src/data/scenarios.json + both scenario page sources); CORS confirmed (*); browser flow verified end-to-end over plain HTTP (ref → commit → tree walk → decrypt, key zhlwx0cCPoS2UDPsy25EnEEH0pymN87bTBzOFzNpkFU); shell live at /scenarios/ (unlinked). Remaining: GRC content review → menu repoint. Author: @website-agent Date: 2026-07-04 Parent: architecture__structure-content-decoupling.md

As built, since v1.0.0. The pilot lives at site/scenarios/ — it moved with the rest of web_overlay/ when the vault publisher was removed and site/ became the deployed tree. The file names below were the plan; what shipped is index.html, rm-dom.js, rm-scenarios.js, rm-scenarios-loader.js, rm-scenarios-schema.js and styles.css, all in that one directory, with the tests at tests/site/test_scenarios_schema.mjs. Everything else in this brief — the vault, the branch-as-environment model, the runtime flow — is unchanged.


0. Scope & success criteria

Move the interactive Risk Scenarios experience to the decoupled model:

Done means: a GRC agent edits a scenario (or flips a live flag) in the content vault, pushes, and the change is on riskmandate.ai/scenarios/ on the next page load — no CI run, no vault re-clone, no repo commit. Rollback at any moment = repoint the menu link back to scenarios.html.

1. Current state (verified against vault v0.8.0)

2. The content vault (rm-scenarios)

Needs from Dinis/vault team: a new vault + its id, the public read key (hex), and write access for the content/GRC agents.

Proposed layout (grain: one file per scenario, so edits and diffs are scoped and two agents can work without colliding):

manifest.json                 { schema: "rm-scenarios/v1",
                                series: { title, buttons, intervals[] },
                                live: ["oauth-token","company-card", …],   ← ordered
                                scenarios: ["s01-email", "s04-card", …] }  ← the bank
scenarios/<id>.json           one per scenario: { id, n, domain, title,
                                hook, escape, act, reveal }

(live moves from a per-item flag to an ordered list in the manifest — the page fetches the manifest + only the live scenarios: typically 5 small GETs.)

Branches = environments: main is what production renders; a dev branch is staging. Promotion is a sgit merge. The shell accepts ?branch=<name> for previewing any branch on any deployment.

3. The repo page (web_overlay/scenarios/index.html)

New files, all repo-owned, all testable:

web_overlay/scenarios/index.html      the shell (chrome + mount point)
web_overlay/_common/rm-vault-content.js   fetch→decrypt→verify glue (reusable)
web_overlay/_common/rm-scenarios.js       the engine, ported from the vault's
                                          scenarios.js — with unit tests
web_overlay/_common/rm-scenarios.css      ported styles
tests/unit/web/…                          engine + glue tests (node:assert)

Runtime flow

load shell → importReadKey(READ_KEY_B64URL)
          → resolve ref(branch) → commit → tree → manifest.json   (vault-client)
          → decrypt manifest → fetch+decrypt live scenarios (parallel GETs)
          → render via rm-scenarios engine (DOMPurify on every content string)
          → failure mode: if the vault is unreachable, render the page chrome
            with a "scenarios are temporarily unavailable" card — never a
            blank page (fail visible, not broken)

Vault-client: import the hosted module sgraph's shells use (sg-vault-client.js — importReadKey, readObject, path resolution) from dev.tools.sgraph.ai, pinned to an exact version in the import map. If we want zero external script origins, vendor the file into _common/ instead — decide at review (vendored copy = we own updates; import = we track theirs).

The key-format gotcha (do not skip)

sgit uses the 64-hex read key; the browser client's importReadKey requires base64url (43 chars) and fails silently on hex. Convert once when the vault is created and embed the base64url form:

import base64
b64u = base64.urlsafe_b64encode(bytes.fromhex(HEX_KEY)).decode().rstrip("=")

Chrome (nav/header) — pilot approach

The shell carries a static copy of the current header/menu (markup + tokens from the v0.8.x design) so the page is standalone and looks native, per the plan. Known cost: chrome drift if the vault redesigns. Accepted for one page; the shared rm-chrome component (fed by a runtime site manifest) is scheduled for when the second area migrates — that's when duplication becomes real rather than speculative.

4. QA & engineering practice (the point of the exercise)

5. Cutover plan

StepActorAction
1Dinis/vault teamcreate rm-scenarios vault; hand id + read key (hex); grant content agents write
2this agentseed the vault from src/data/scenarios.json (split per §2), on branch main
3this agentbuild shell + engine + tests; deploy via qa lane; verify at /scenarios/ (unlinked — safe)
4GRC/content agentreview content renders correctly; edit-and-reload test (the "done" criterion)
5vault teamrepoint menu "Risk Scenarios → Interactive" → /scenarios/ (one line + rebuild)
6—monitor; old scenarios.html remains in the vault untouched as instant rollback

Rollback: repoint the link back. Nothing else to undo.

6. Explicitly out of scope (follow-ups)

7. Open questions

  1. Vault granularity: one rm-scenarios vault (proposed) vs one shared rm-content vault with per-area folders? Per-area vaults give scoped keys and rotation; shared gives fewer keys to track. Proposal: per-area.
  2. Vendored vault-client vs hosted import (see §3).
  3. Does dev.send.sgraph.ai send permissive CORS for browser GETs from riskmandate.ai? (Blocking for step 3; already asked in comms msg 001.)
  4. Should the statics (LinkedIn share images) live in the same vault as binary assets, exercising vault: asset fetching in the shell?