Skip to content

fix(provider-gen): make the shared runtime app-independent - #33

Draft
k08200 wants to merge 2 commits into
spike/gen-providerfrom
spike/gen-provider-generic-runtime
Draft

fix(provider-gen): make the shared runtime app-independent#33
k08200 wants to merge 2 commits into
spike/gen-providerfrom
spike/gen-provider-generic-runtime

Conversation

@k08200

@k08200 k08200 commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

Stacked on #29 (base spike/gen-provider), closing the A1 gap found while reviewing that spike.

The spike's "one generic hand-written runtime" was not generic. runtime.mjs hardcoded POST_ID_TYPE: "post", USER_ID_TYPE: "user", and STORY_ID_TYPE: "story", while the generated module destructured those names out of helpers — so a second app had no way to supply its own. The values were also wrong: the hand-written provider tags keys with app.instagram@1::PostId, not post. This went unnoticed because keyText was stubbed to (v) => String(v), which ignores the type argument entirely, and the harness fed plain strings instead of Uhura wire values. The declared id types were decorative.

This change:

  • Key tags become generated data. The module publishes export const MODULE — the Uhura package identity it was generated for — and derives const POST_ID_TYPE = \${MODULE}::PostId`from it.helpers` is now exactly the four app-independent functions.
  • The identity is read, not guessed. read_module_identity loads the client's own uhura.toml through uhura_check::project_manifest and uses package_id(), matching the file's existing rule of refusing unknown types rather than inferring them. spock gen provider gains --uhura <project>.
  • The port boundary checks again. keyText, textValue, boolValue, and requiredField recover the hand-written provider's semantics, so a key carrying another app's type is refused instead of coerced.
  • One id-type definition. id_type_name now feeds both the generated machine types and the provider key tags, so they cannot drift apart.

Goldens are unchanged: only the generated module's wrapper moved, so the char-equality proofs against the hand-written provider still hold.

Type

fix

Checklist

  • The shared runtime names no app; a second app drives it with no runtime edit
  • Key types are generated from the client's real package identity
  • Port type checking restored to the hand-written provider's semantics
  • Existing char-equality goldens unaffected
  • Draft: depends on spike: spock gen provider — assembly-layer tables from the contract #29; naming ("wire"), declaration home, and the remaining spike gaps are still open there

Test plan

Run on the pinned toolchain (1.92.0) and node 24.18.0, after the CI prerequisite pnpm -C uhura/web build:provider:

  • cargo fmt --all --check — exit 0
  • cargo clippy --locked --workspace --all-targets -- -D warnings — exit 0
  • cargo test --locked --workspace — 405 passed, 0 failed
  • cargo test --locked --workspace --all-targets — 0 failed
  • cargo test --locked -p spock-cli --test provider_gen -- --ignored — 3 passed (runtime ok, genericity ok, second app ok)
  • cargo run -p spock-cli -- check examples/instagram/v0.spock — exit 0
  • cargo run -p spock-cli -- check uhura/examples/instagram — exit 0
  • node scripts/check-doc-snippets.mjs — 34 snippets checked, 0 skipped
  • cargo run -p spock-cli -- gen provider uhura/examples/instagram/backend/app.spock --app crates/spock-cli/tests/provider_fixtures/instagram.wire --uhura uhura/examples/instagram/client — emits export const MODULE = "app.instagram@1" read from the real client manifest
  • That CLI output, driven against the unmodified runtime: runtime ok and genericity ok

Before the fix, the new harness fails as expected:

AssertionError: runtime hardcodes app id types: POST_ID_TYPE, USER_ID_TYPE, STORY_ID_TYPE

The spike's shared runtime hardcoded Instagram's key types and stubbed the
port check that consumes them, so the declared id types were decorative and a
second app could not use the runtime at all.

Key tags are app data, so they are generated: the module now publishes the
Uhura package identity it was built for and derives `POST_ID_TYPE` and friends
from it, leaving `helpers` as exactly the four app-independent functions. The
identity is read from the client's own `uhura.toml` through
`uhura_check::project_manifest`, never guessed from the app name.

`keyText`, `textValue`, `boolValue`, and `requiredField` recover the checking
semantics of the hand-written provider, so a key carrying the wrong Uhura type
is refused at the port boundary instead of being coerced with `String(v)`.

One `id_type_name` definition now feeds both the generated machine types and
the provider key tags, so the two cannot drift apart.

Verified: fmt, clippy -D warnings, `cargo test --locked --workspace`
(405 passed), the node harness (`-- --ignored`, 3 passed), doc snippets
(34), both `check` examples, and `spock gen provider --uhura` end to end
against the real client manifest, whose output drives the runtime unchanged.
@vercel

vercel Bot commented Jul 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spock Ready Ready Preview, Comment Jul 27, 2026 8:10am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6759389e-3b6e-419d-a1a9-98cb967335df

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch spike/gen-provider-generic-runtime

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The harness carried `#[ignore = "requires node"]` on the premise that CI does
not have node. That premise is false: the test job installs node from `.nvmrc`
and runs `pnpm -C uhura/web build:provider` before cargo, and the workspace
cannot go green without it — `spock-host` asserts on the Play artifacts that
build produces. Node is already mandatory, so the harness was opt-out for no
reason, and the two tests proving the runtime is app-independent never ran.

Two of these tests also wrote the same `provider-tables.mjs` under one shared
temp directory, which becomes a race once they run in the default suite. Each
now writes its own file.

Verified: `cargo test --locked -p spock-cli --test provider_gen` reports
14 passed, 0 ignored (was 11 passed, 3 ignored); fmt, clippy -D warnings, and
`cargo test --locked --workspace` stay green.
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