Skip to content

docs: make the plugin hub-ready and self-explanatory for operators - #9

Merged
Weegy merged 1 commit into
mainfrom
docs/hub-annotations
Aug 21, 2026
Merged

docs: make the plugin hub-ready and self-explanatory for operators#9
Weegy merged 1 commit into
mainfrom
docs/hub-annotations

Conversation

@Weegy

@Weegy Weegy commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Why

The hub does not store manifest.yaml — it projects it. parsePublish
(omadia-hub/lib/manifest.ts:113-231) lifts a fixed set of fields into the
registry index and discards everything else. Two of the discards matter:

  • optional_requires is never read (:221-223 name provides, requires
    and depends_on, and nothing else). The four capabilities this plugin is
    written to survive the absence of — and the degradation it takes for each —
    were invisible to anyone deciding whether to install it.
  • Every comment in the file. parseYaml keeps values, not trivia. All the
    careful rationale in this manifest is for whoever edits it, never for an
    operator.

Meanwhile packages/plugin/README.md, which ships inside the ZIP and is the
first thing an operator reads after unzipping, still described 0.1.0: "Nothing
yet… contributes no routes… Permissions: none declared."

What changed

packages/plugin/manifest.yaml

  • setup.guide (en + de) now carries what the registry cannot: the two
    operator grants and how to perform each, the Fly-vs-Docker runner choice, the
    ledger-handoff dry run, and a degradation table for every optional
    capability. The German guide was three sections behind English; it is now at
    parity.
  • setup.fields: all 21 entries get label and help as { en, de }
    maps — the shape core normalises through manifestLocalized.normalizeLocalized
    (OM-17/15: Google Workspace plugin manifest needs format validation, German labels, and prerequisites on the card omadia#602).
  • compat.core >=1.0 <2.0>=1.5 <2.0 (reasoning below).
  • identity.description rewritten for the storefront card; categories
    extended with automation and github.
  • A header comment recording the kept/stripped split with omadia-hub
    file:line, so the next operator-facing block does not get added somewhere that
    is discarded at publish time.

The SQL grant has no UI, and the guide now says so

middleware/src/platform/pluginSqlGrants.ts records it twice in its own source
"plugin_sql_grants still has no shipped grant surface — nothing in src/
calls grant()"
(:79-81, :184-185). The hardcoded ramp
(LEGACY_SQL_GRANTS_2026_08_20) covers four bundled plugins; this one is
installed, not bundled.

So rather than leaving "grant the SQL permission" with no way to do it, the
guide documents the manual INSERT it currently is. The public-path grant
does have a shipped surface and is documented as the endpoint it is:
PUT /api/v1/admin/runtime/installed/:id/public-paths.

compat.core reasoning

Extension point Core PR
C4 operator-granted public_paths #791 era
C6 route auth modes + raw body #791
C7 permissions.sql gate #787
C9 optional_requires + getOptional #802 → plugin-api 1.3.0
C11 ctx.sql.seedLedger #806 → plugin-api 1.5.0

C15 (permissions.sql.handoff, added by #8) wants plugin-api 1.6.0 and does
not raise the floor, because it degrades cleanly: an older core ignores the
unknown key and the activate() seedLedger call remains the thing that
performs the handoff. The floor tracks what this plugin cannot run without, not
what it would prefer.

C11 is newest, so 1.5.0 is the floor. Core never semver-compares
compat_coremanifestLoader.ts:503 and registryClient.ts:415 only carry
the string through to the store view — which is exactly why it has to be honest
rather than permissive: on a 1.4.0 core ctx.sql.seedLedger is undefined, the
handoff silently does not happen, and the migrations re-run against a schema
core already created.

Documentation

  • docs/OPERATOR-GUIDE.md (new) — install, the two grants, credentials,
    runner backends, migration handoff (with the real --plan / --apply CLI
    contract), uninstall/purge, troubleshooting, known issues.
  • README.md — rewritten from "Status: P0 — scaffold / Nothing has moved
    yet"
    to the current release, with a mermaid architecture diagram. 269 lines.
  • packages/plugin/README.md — the in-ZIP operator README, rewritten.
  • CHANGELOG.md — 0.1.0 and 0.2.0 reconstructed from the history, 0.2.0
    expanded from three lines, plus an Unreleased section for 0.3.1.
  • CONTRIBUTING.md — a section on keeping the four operator-facing
    documents in step, and the two rules that are easy to get wrong.

Verification

typecheck   PASS
build       PASS
tests       1264 pass / 0 fail / 1 skipped (pg suites skip without a DB)
package     PASS -> omadia-dev-platform-0.3.1.zip (537,065 bytes)

No version bump of its own — rebased onto #8, so the artifact is 0.3.1 and
the drift guard still agrees with package.json.

The cut ZIP was additionally run through the hub's own parsePublish (real
fflate + yaml, real gates) to confirm it publishes cleanly and to check what
the index actually ends up holding:

PASS  schema_version === "1"      PASS  pkg.name === identity.id
PASS  identity present            PASS  pkg.version === identity.version
PASS  kind valid

version     : 0.3.1              setup_fields : 21 (all with en+de)
compat_core : >=1.5 <2.0          requires     : ["graphPool@1"]
guide       : en=7754c, de=8175c

dropped top-level keys : lifecycle, optional_requires

That last line is the whole reason for this PR.

Notes for review

  • This is documentation only. No source, no behaviour, no version bump.
  • Rebased onto feat: declare the ledger handoff in the manifest so the kernel runs it (0.3.1) #8 (0.3.1, C15). Its permissions.sql.handoff key and the
    0.3.1 CHANGELOG section are preserved intact; this PR's documentation work is
    folded in under the same 0.3.1 heading. The only conflict was in
    CHANGELOG.md; manifest.yaml merged cleanly.
  • G7 status updated throughout now that feat: declare the ledger handoff in the manifest so the kernel runs it (0.3.1) #8 fixes it: the operator guide,
    README and manifest all record that the fix needs plugin-api 1.6.0 and that
    the gap persists below it.
  • One known cosmetic gap, in a different repo. The hub's SetupRow prints
    label through asText, which JSON.stringifys a non-string
    (app/p/[...id]/page.tsx:243-259), so the {en,de} maps render as raw JSON
    in the storefront's setup-fields table. Core's install wizard — the surface
    where an operator actually fills these in — resolves them correctly. The fix
    is one line in omadia-hub; the maps are deliberately not flattened back to
    bare English strings to work around it, since that would take German away from
    the wizard to protect a display bug.

The hub does not store this manifest, it PROJECTS it. `parsePublish`
(omadia-hub/lib/manifest.ts:113-231) keeps identity, compat.core,
setup.fields, setup.guide, provides/requires/depends_on and permissions,
and throws away everything else — including `optional_requires` and every
comment in the file. So the four capabilities this plugin is designed to
survive the absence of, and the degradation it takes for each, were
invisible to anyone deciding whether to install it.

manifest.yaml
- setup.guide (en + de) now carries what the registry cannot: the two
  operator grants and how to perform them, the runner backends, the
  ledger handoff dry-run, and a degradation table for each optional
  capability. The German guide was three sections behind; it is at parity.
- Every setup.fields entry gets label + help as `{ en, de }` maps, the
  shape core normalises through manifestLocalized.normalizeLocalized
  (byte5ai/omadia#602). 21 fields, both locales.
- compat.core `>=1.0 <2.0` -> `>=1.5 <2.0`. Each of C4/C6/C7/C9/C11 is
  traced to the core PR that shipped it; C11 is newest, and it landed in
  @omadia/plugin-api 1.5.0. Core never semver-compares compat_core
  (manifestLoader.ts:503 and registryClient.ts:415 only carry the string
  through to the store view), which is precisely why it has to be honest
  rather than permissive: on a 1.4.0 core `ctx.sql.seedLedger` is
  undefined and the handoff silently does not happen.
- A header comment recording the kept/stripped split with file:line, so
  the next operator-facing block does not get added somewhere that is
  discarded at publish time.

The SQL grant has no UI. `pluginSqlGrants.ts` says so twice in its own
source — nothing in core's `src/` calls `grant()`, and the bundled ramp
covers four bundled plugins this one is not among. Documented as the
manual INSERT it currently is, rather than left as "grant the SQL
permission" with no way to do it. The public-path grant does have a
shipped surface and is documented as the endpoint it is.

packages/plugin/README.md ships INSIDE the ZIP and still described 0.1.0:
"Nothing yet", "no routes", "Permissions: none declared". It is the first
thing an operator reads after unzipping. Rewritten for what 0.3.0 does.

Also: docs/OPERATOR-GUIDE.md (the runbook the READMEs link to), a root
README rewritten from "Status: P0 - scaffold" to the current release with
an architecture diagram, CHANGELOG entries for 0.1.0 and 0.2.0
reconstructed from the history plus an Unreleased section, and a
CONTRIBUTING section on keeping the four operator-facing documents in
step.

Verified: typecheck, build, 1269 tests and `npm run package` all pass;
version unchanged at 0.3.0 so the drift guard still agrees. The cut ZIP
was run through the hub's own parsePublish to confirm every gate passes
and to check what the index actually ends up holding.
@Weegy
Weegy force-pushed the docs/hub-annotations branch from 48640f6 to b7e9121 Compare August 21, 2026 06:55
@Weegy
Weegy merged commit ec4a2b7 into main Aug 21, 2026
3 checks passed
@Weegy
Weegy deleted the docs/hub-annotations branch August 21, 2026 06:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant