Skip to content

feat(model-provider): offers/runs contract, openai_compat + h3_video adapters (stacked on collaboration-candidate) - #17

Closed
SashaMIT wants to merge 3 commits into
review/collaboration-candidatefrom
feat/model-provider-rebase
Closed

SashaMIT wants to merge 3 commits into
review/collaboration-candidatefrom
feat/model-provider-rebase

Conversation

@SashaMIT

@SashaMIT SashaMIT commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

One commit (3027d9540, +2473, 17 files) stacked on the frozen review/collaboration-candidate tip (b07160cf1). Rebase completed with zero textual conflicts; one semantic drift found and fixed (new GatewayState collaboration fields in gateway_tests/model.rs).

Adds the model-provider capsule and its Runtime integration:

  • capsules/model-provider/: offers/runs contract with two adapters — openai_compat (chat) and h3_video (video). SSRF-closed: upstream URLs come only from Init extra (operator config), never from requests. No env vars. No placeholder DIDs in offers.
  • elastos-server/src/provider_resource.rs: maps model scheme ops to capability resources (elastos://model/<offer_id>/<op>); unknown ops fail closed.
  • elastos-server/src/server_infra.rs: spawns and registers the capsule alongside existing providers.
  • elastos-server/src/api/gateway_provider_proxy.rs: Home-gui-token-gated ops (offers_list, runs_create, runs_get, runs_events, runs_cancel, ping).
  • elastos-server/src/api/gateway_tests/model.rs: 12 gateway tests.
  • scripts/model-provider-smoke.sh: operator smoke harness.

Verification (gate run on this branch, 14 Aug)

  • cargo fmt --all -- --check — clean
  • git diff --check — clean
  • scripts/check-wci-alignment.sh — OK
  • cargo test -p elastos-server model — 12 passed, 0 failed

Known follow-ups (not claimed here)

  • A1 — gateway allowslist currently Home-shell-only; other shells get 404 until grant placement is decided (Q2).
  • A2 — grant enforcement on the Home-path runs_create is not yet wired; where should it live? (Q2)
  • A6 — components.json packaging for the capsule not included (Q4).
  • A11 — run handles are not scoped per principal: any Home token can runs_get/runs_events/runs_cancel any run_id. We did not improvise a capsule-side ACL; see Q3.

Questions for Anders

  • Q1 — Is stacked-on-review/collaboration-candidate the right base, or do you want this retargeted to upstream/0.7-dev? (One commit; retarget is cheap.)
  • Q2 — Where does grant enforcement for Home-path provider ops belong — Runtime Inbox grant flow at the gateway layer, or inside the provider session path? We removed our gateway-side grant store per the Runtime-owns-grants law and want to wire enforcement at the layer you intend.
  • Q3 — How should run handles be scoped to the launching principal (A11)? Should the Runtime issue per-run capabilities, or should the gateway bind run_id to the session that created it?
  • Q4 — Does components.json packaging for new capsules belong in this PR or in your release process?
  • Q5 — Contract flags from our feat/protected-content-contracts review (38/38 tests green, spec fully matched):
    1. CarrierEndpointId tightening — any wire-compat impact on Irzhy's dKMS port if the encoding narrows?
    2. Tracking surface — should integration consumers track against TASKS.md items or a dedicated contracts README section?
    3. Nonce entropy — worth a note in the integration spec that replay-claim nonces MUST be CSPRNG-generated (not counters), or is that deliberately left to implementers?

Test plan

  • cargo test -p elastos-server model (12/12)
  • fmt / diff-check / wci-alignment gate
  • Operator smoke (scripts/model-provider-smoke.sh) against live pair A — pending Sparks availability
  • Anders review of boundary adherence (capsule shape, resource mapping, gateway surface)

Made with Cursor

Part of #84.
Part of #85.

SashaMIT and others added 3 commits August 14, 2026 13:44
…adapters (P0–P3)

Anders-aligned model provider capsule: one contract for inference from
any backend (local, Sparks/LAN, Carrier-reached, hosted).
- offer/run JSON schemas (elastos.model.offer/v1); offers_list gated on
  configured backends (flash_url / h3_url from env — SSRF-closed)
- run state machine + registry with concurrency policy; runs_get returns
  full events; runs_cancel cooperative
- openai_compat adapter: Flash chat, content:null/reasoning quirk
  normalization, policy_violation error codes
- h3_video adapter: multipart submit, streaming download to .partial,
  sha256 mid-stream, content-addressed rename (32-hex id), dogfood
  sidecar json
- plumbing: registry reserved name, spawn block, provider proxy
  allowlist, provider_resource model arm + fail-closed tests
- scripts/model-provider-smoke.sh: end-to-end P0–P3 gate harness

Gates: docs/00-handoff/model-provider-gates/P0..P3 in Sparks.
Co-authored-by: Cursor <cursoragent@cursor.com>
…e, control-plane registration

Ports the dogfooded esp capsule shape onto the rebased base:

- offer.rs: model descriptor wrapped in elastos.service.offer/v1 with
  service_kind "model" (Anders' publish contract); no placeholder DIDs.
- main.rs: offers derive from configured services only — no fallback offer;
  runs_create on an unconfigured chat backend fails closed with
  "chat backend is not configured" instead of dispatching to an empty URL.
- adapters: drop wall-clock run ceilings (caller owns the compute; runs end
  on completion, cancel, or genuine upstream failure); h3_video artifacts are
  content-addressed (sha256[..32]) with .partial → atomic rename.
- server_infra: register model-provider on the gateway control-plane path
  too (spawn_host_providers=false), passing operator env (OLLAMA_URL/
  OLLAMA_MODEL/CREATIVE_URL) through Init config.extra — SSRF-closed,
  matching the ai-provider pattern. llama/ai/availability gating unchanged.
- gateway_provider_proxy: record that per-principal grant enforcement for
  model/runs_create is Runtime-owned; no provider-side grant store.
- gateway_tests/model: runs_create dispatch via app allowlist (interim,
  pre Runtime grant enforcement).

Co-authored-by: Cursor <cursoragent@cursor.com>
…cement test

- run.rs: terminal runs carry terminal_at and are evicted on the next
  create after a 10-minute TTL. The registry is a run surface, not a
  retention store — offer policy declares data_retention_seconds: 0; the
  TTL exists only so clients can fetch final events/artifacts. 3 unit tests.
- handlers/provider.rs tests: prove the session path derives
  elastos://model/<offer>/runs_create + Action::Execute and that
  enforce_capability denies tokenless delegated calls and Read-scoped
  tokens, and admits an Execute token (A15).

Resolved without code change:
- A13 (cancel honesty): the ported adapters already check the cancel flag
  between stream chunks and mid-download, removing .partial output; the
  h3_video header documents that the sync upstream has no remote abort.
- A14 (audit_events): every provider capsule's manifest declares
  audit_events as Runtime-projection policy (19/19 capsules) — the
  declaration is the convention, emission is Runtime-side. No deviation;
  wiring lands with the Runtime grant work.

Co-authored-by: Cursor <cursoragent@cursor.com>
@andersalm

Copy link
Copy Markdown
Contributor

For the base, I think the model-provider core should be extracted onto upstream/0.7-dev. The current implementation does not materially depend on collaboration. Principal-scoped service grants, signed remote offers and Carrier routing are still follow-up work. Once the core and collaboration candidate are accepted, a smaller integration branch can connect them. Keeping the current base is reasonable only if we intentionally make #17 dependent on the collaboration candidate landing first. This requires replaying the model commits onto upstream/0.7-dev, not merely changing the PR base on GitHub.

For grants, Inbox should handle the approval experience, while the common Runtime provider boundary enforces the resulting grant. The Home gateway should authenticate the launch, derive the principal and session, then enter that same Runtime path. The model provider should not maintain a separate grant store. The current Home route still dispatches after checking only the Home token, so this remains open.

Runs should belong to the stable principal, not only the temporary session. Runtime should keep the mapping to the provider run and issue a narrow per-run capability or opaque handle. This allows a later authenticated session belonging to the same principal to recover the run. It also provides a clean path for revocation and deliberate delegation.

Packaging can be a separate stacked slice, but it must land before the feature is called installable. The current components.json entry is incomplete because source-home does not build or install the provider. We also need to resolve the execution mismatch: the manifest declares a MicroVM capsule, while Runtime starts a native host binary.

For the protected-content questions, I cannot find CarrierEndpointId in the current published contracts or dKMS branch. The contracts intentionally keep endpoints and routes outside signed objects. Please point me to the proposed type or commit if there is a concrete encoding change to review. Consumers should use the versioned contract crate and specification, while TASKS.md tracks unfinished integration work. Runtime-generated replay nonces and opaque bindings should use an OS CSPRNG. Randomness should remain outside the deterministic contracts crate.

A few implementation details also need correction. The current provider reaches LAN or hosted backends through direct HTTP rather than the future Runtime-selected Carrier route, and video output is written directly into the Library directory layout instead of crossing the Runtime object boundary. The video offer advertises settings the implementation rejects, accepts a reference input it ignores, and ignores the configured chat model name. The old ai-provider and llama-provider paths also remain active, so this is not yet the single canonical model path.

The smoke script uses an undefined variable, expects the old video filename format and expects a duration limit that the implementation does not enforce.

The offers/runs direction is good and worth preserving, but principal grants, run ownership, truthful packaging, transport and object boundaries, contract accuracy and working proof should be addressed before merge.

@SashaMIT

Copy link
Copy Markdown
Contributor Author

Not implementing #17 this week — leaving it open as the offers/runs direction you said to preserve.

Your review stands and we will not merge this stack as-is:

  • Replay the model-provider core onto upstream/0.7-dev (not a GitHub retarget of this PR). Collaboration grants, signed remote offers, and Carrier routing stay a later integration branch.
  • Inbox owns the approval experience; the common Runtime provider boundary enforces the grant. Home gateway authenticates launch, derives principal/session, then enters that same path. No provider grant store.
  • Runs belong to the stable principal, with a Runtime-owned mapping and a narrow per-run handle so a later session of the same principal can recover the run.
  • Packaging is a stacked slice before anything is called installable. Native host binary vs microvm manifest mismatch stays open.
  • Direct HTTP, Library-path video writes, offer-descriptor lies, and the still-live ai-provider / llama-provider paths are known — this is not the single canonical Model path yet.

Current Home ask for review is #23 (first-run URUX on the harness freeze). After that lands and you name the base, we will come back to a smaller 0.7-dev extraction rather than keep stacking on review/collaboration-candidate.

@irzhywau irzhywau added this to the 0.7.1 milestone Sep 29, 2026
@andersalm

Copy link
Copy Markdown
Contributor

@SashaMIT superseded by the current model contract.
Move any unique ideas to issues and close?

@andersalm

Copy link
Copy Markdown
Contributor

@SashaMIT confirmed: please close (superseded by the current model contract); move any idea worth keeping to an issue first.

@SashaMIT

SashaMIT commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Closing as superseded by the current model contract. I checked develop: elastos-model-contract, provider_resource.rs and the h3_video adapter exist there, and docs/MODEL_PROVIDER.md binds runs to the consumer principal, capsule and run (this PR's open A11).
No unique idea is left to move to an issue; the original commit 3027d95 stays on branch feat/model-provider-rebase.

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.

3 participants