Skip to content

feat: add principal field to ipc-message record - #4

Merged
joshuajbouw merged 1 commit into
mainfrom
feat/ipc-message-principal
May 18, 2026
Merged

feat: add principal field to ipc-message record#4
joshuajbouw merged 1 commit into
mainfrom
feat/ipc-message-principal

Conversation

@joshuajbouw

@joshuajbouw joshuajbouw commented May 18, 2026

Copy link
Copy Markdown
Member

Summary

Closes the subscribe-side gap from unicity-astrid/sdk-rust#37. ipc-publish-as (PR #3 here) lets uplinks stamp outgoing messages with a claimed principal, but subscribers had no per-message way to read it back. Adds principal: option<string> to the ipc-message record.

Why this is needed

unicity-astrid/astrid#735 installs the invocation context from the first message of an ipc::recv batch — host calls the subscriber makes after recv attribute to that publisher. Covers single-message subscribers. Breaks down for multi-message batches where messages 1..N may have different publishers: the subscriber sees msg[0]'s principal as the invocation context for all of them.

Surfacing the principal per-message lets subscribers route / log / authorize correctly without relying on the invocation-context shortcut.

Semantics

  • For messages published via ipc-publish: host stamps the publisher's invocation principal (whoever the host attributed the call to).
  • For messages published via ipc-publish-as: host stamps the principal the uplink claimed.
  • none for kernel-originated events with no attributable principal, and for legacy messages that predate this field.

Backward compatibility

option<string> by construction. Existing subscribers ignore the new field; existing publishers don't need to change anything (the kernel populates the field on their behalf based on caller context).

Follow-up work in consumers (separate PRs, blocked on this merging)

  • unicity-astrid/astrid: kernel stamps the field on the publish path (both ipc-publish and ipc-publish-as), bumps contracts/ submodule, re-syncs core/wit/.
  • unicity-astrid/sdk-rust: bumps submodule, re-runs sync-host-wit.sh, surfaces principal: Option<String> on the SDK's Message struct + envelope_to_poll_result helper.
  • unicity-astrid/sdk-js: bumps submodule, surfaces principal on the IpcMessage type and the Subscription mapping.

Test plan

  • WIT parses (wasm-tools component wit-level validation will happen in each consumer's CI once the submodule bumps land).
  • Kernel stamps the field correctly on both publish paths (in the kernel PR).
  • Round-trip across recv: subscriber reads expected principal per message (validated end-to-end in the kernel PR's integration test).

Addresses the subscribe-side gap from astrid-runtime/sdk-rust#37:
`ipc-publish-as` lets uplinks stamp outgoing messages with a claimed
principal, but subscribers had no per-message way to read it back.

The kernel-side fix in astrid-runtime/astrid#735 installs the invocation
context from the FIRST message of an ipc::recv batch — host calls the
subscriber makes after recv attribute to that publisher. That covers
single-message subscribers, but breaks down for multi-message batches
where messages 1..N may have different publishers. Subscribers need to
see the publisher per-message.

The new `principal: option<string>` field on ipc-message surfaces it:

- For messages published via `ipc-publish`, the host stamps the
  publisher's invocation principal (whoever the host attributed the
  call to).
- For messages published via `ipc-publish-as`, the host stamps the
  principal the uplink claimed.
- `none` for kernel-originated events with no attributable principal,
  and for legacy messages that predate this field. Backward-compatible
  by construction: existing subscribers ignore the new field.

Follow-up work in consumers:

- unicity-astrid/astrid: kernel stamps the field on publish path
  (both ipc-publish and ipc-publish-as), bumps contracts/ submodule,
  re-syncs core/wit/.
- unicity-astrid/sdk-rust: bumps contracts/ submodule, re-runs
  sync-host-wit.sh, surfaces `principal: Option<String>` on the SDK's
  `Message` struct + `envelope_to_poll_result` helper.
- unicity-astrid/sdk-js: bumps submodule, surfaces principal on the
  `IpcMessage` type and the `Subscription` mapping.
@joshuajbouw
joshuajbouw merged commit 65bd8e7 into main May 18, 2026
@joshuajbouw
joshuajbouw deleted the feat/ipc-message-principal branch May 18, 2026 15:59
joshuajbouw added a commit to astrid-runtime/sdk-rust that referenced this pull request May 19, 2026
Adds the receiving-side half of the ipc-publish-as feature. The
canonical WIT (astrid-runtime/wit#4) added a principal: option<string>
field to the ipc-message record; this PR consumes it.

- Bumps contracts/ submodule to the PR-4 merge commit (65bd8e7).
- Re-runs scripts/sync-host-wit.sh — astrid-sys/wit/astrid-capsule.wit
  picks up the new field. The wit-bindgen-generated
  astrid_sys::astrid::capsule::ipc::IpcMessage now carries
  principal: Option<String>.
- Surfaces the field on the SDK's astrid_sdk::ipc::Message struct.
- envelope_to_poll_result copies the new field from the WIT envelope
  through to the user-facing PollResult.

Why subscribers need per-message principal: kernel PR #735 installs an
invocation context from the FIRST message of a recv batch — host calls
the subscriber makes after recv attribute to that publisher. Covers
single-message subscribers. Breaks down for multi-message batches where
messages 1..N may have different publishers: the subscriber sees msg[0]'s
principal for all of them.

Surfacing the principal per-message lets subscribers route / log /
authorize correctly without relying on the invocation-context shortcut.

Until the kernel publish path stamps the field (separate follow-up PR
on unicity-astrid/astrid), the field will be None at runtime for every
message — but the contract is now in place and the SDK surface is ready
to consume real data the moment the kernel side lands.

cargo build --workspace passes.
joshuajbouw added a commit to astrid-runtime/sdk-js that referenced this pull request May 19, 2026
Mirrors unicity-astrid/sdk-rust's feat/ipc-message-principal change.
Canonical WIT (astrid-runtime/wit#4) added principal: option<string>
to the ipc-message record; this PR consumes it on the JS side.

- Bumps contracts/ submodule to PR-4 merge (65bd8e7).
- Updates wit-imports.d.ts: IpcMessage now carries
  `principal: string | undefined` matching the canonical WIT.
- Updates packages/astrid-sdk/src/ipc.ts IpcMessage interface and
  the envelope-to-PollResult mapper to plumb the new field through.
- Adds tsconfig.tsbuildinfo to .gitignore (slipped through the
  initial commit's ignore set).

Until the kernel publish path stamps the field (separate follow-up
PR on unicity-astrid/astrid), the field is undefined at runtime for
every message — contract is in place, SDK surface is ready to
consume real data the moment the kernel side lands.

npx tsc -b packages/astrid-sdk passes.
joshuajbouw added a commit to astrid-runtime/sdk-rust that referenced this pull request May 19, 2026
Adds the receiving-side half of the ipc-publish-as feature. The
canonical WIT (astrid-runtime/wit#4) added a principal: option<string>
field to the ipc-message record; this PR consumes it.

- Bumps contracts/ submodule to the PR-4 merge commit (65bd8e7).
- Re-runs scripts/sync-host-wit.sh — astrid-sys/wit/astrid-capsule.wit
  picks up the new field. The wit-bindgen-generated
  astrid_sys::astrid::capsule::ipc::IpcMessage now carries
  principal: Option<String>.
- Surfaces the field on the SDK's astrid_sdk::ipc::Message struct.
- envelope_to_poll_result copies the new field from the WIT envelope
  through to the user-facing PollResult.

Why subscribers need per-message principal: kernel PR #735 installs an
invocation context from the FIRST message of a recv batch — host calls
the subscriber makes after recv attribute to that publisher. Covers
single-message subscribers. Breaks down for multi-message batches where
messages 1..N may have different publishers: the subscriber sees msg[0]'s
principal for all of them.

Surfacing the principal per-message lets subscribers route / log /
authorize correctly without relying on the invocation-context shortcut.

Until the kernel publish path stamps the field (separate follow-up PR
on unicity-astrid/astrid), the field will be None at runtime for every
message — but the contract is now in place and the SDK surface is ready
to consume real data the moment the kernel side lands.

cargo build --workspace passes.
joshuajbouw added a commit to astrid-runtime/sdk-js that referenced this pull request May 19, 2026
## Summary

Adds the receive-side half of the `ipc-publish-as` feature on the JS
side. Canonical WIT PR `astrid-runtime/wit#4` added `principal:
option<string>` to the `ipc-message` record; this PR consumes it.
Mirrors `unicity-astrid/sdk-rust`'s companion PR #41.

## Changes

- `packages/astrid-sdk/src/wit-imports.d.ts` — `IpcMessage` ambient
declaration now carries `principal: string | undefined` matching the
canonical WIT.
- `packages/astrid-sdk/src/ipc.ts` — adds `principal` to the user-facing
`IpcMessage` interface with docstring describing `Some`/`None`
semantics. The envelope-to-PollResult mapper plumbs the new field
through.
- `.gitignore` — adds `tsconfig.tsbuildinfo` (slipped through the
initial commit's ignore set) and untracks the existing file.

## Why subscribers need per-message principal

The kernel's per-recv invocation-context install (analogous to
`astrid-runtime/astrid#735`) handles the single-message case for the
SDK's call-context model — but for multi-message `recv` batches where
messages 1..N may have different publishers, the subscriber has no
per-message way to read it back. `IpcMessage.principal` closes that gap.

Until the kernel publish path stamps the field, the field is `undefined`
at runtime for every message — contract is now in place, SDK surface is
ready to consume real data the moment the kernel side lands.

## Test plan

- [x] `npx tsc -b packages/astrid-sdk` — clean.
- [x] Rebased onto `main`'s tip after PR #1 landed (the other Claude's
contracts-canonicalization work). No conflicts in this PR's files.
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