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

Reading room · sgit.ai

On this page

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

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

API: append lanes (sgit.ai)

The six append endpoints) the write-only vault-to-vault message transport. Four separated capabilities, the blind write response, server-assigned sortable filenames, idempotent mark-processed, and the limits.

Source: https://sgit.ai/api/append-lanes.html↗ · site v0.6.8 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a .md twin; internal links below point at them.


Home↗ / API↗ / Append lanes

Append lanes

A write-only channel attached to a vault, gated by a token the writer holds and nothing else. This is the transport behind vault-to-vault messaging↗ and behind sg.append↗ in the browser bridge, and it is deliberately generic: the same primitive carries messages, logs, signals, control messages and state flows.

Naming. This API was called inbox before v0.32.7. Every /api/vault/inbox/* URL is gone, and purge takes folder:"pending" or "processed", the old "inbox" value returns 400. If you are reading older material, translate.

The six endpoints

All POST, all under /api/vault/append/.

PathGateDoes
configure/{vault_id}x-sgraph-vault-write-keyRegisters append_anchors, hashes of accepted senders, and enum_key_hash
write/{vault_id}append_tokenin the bodyAppends a payload. Account-less: no access token required
list/{vault_id}x-sgraph-vault-enum-keyPaginated listing, optionally with inline content
fetch/{vault_id}enum keyFetch specific file IDs, batched
mark-processed/{vault_id}enum keyMoves pending → processed. Idempotent
purge/{vault_id}write keyDeletes. `folder: "pending""processed"`

Why the gates are split this way

Four capabilities, and the split is the whole design:

CapabilityHolderCanCannot
append_tokenthe senderwritelist, fetch, read anything
enum_keythe vault ownerlist, fetch, mark-processedwrite, purge
write_keythe vault ownerconfigure, purgenone
private keythe vault ownerdecryptnever sent to the server

A sender can put something into your vault and learn nothing at all, not the contents, not the volume, not whether anyone else writes there. The server stores SHA-256 of the first three capabilities and compares hashes; the fourth it never sees.

Four contracts worth relying on

From a vault app: one verb crosses vaults, five do not

This is the constraint to understand before designing anything that spans two vaults, and it was undocumented until the SG/API team's review of 6 September 2026 (quoted here CC BY 4.0). The bridge builds one client bound to the currently open vault, with the enum key derived from that vault's read key. So:

VerbWhich vault it acts onBridge permission
writeAny: it takes an explicit vault_id and posts with no headers at allappend.write
listAlways the open vault. There is no way to address a remote vault with these from an appappend.list
fetchappend.read, notappend.fetch
markProcessedappend.markProcessed
purgeappend.purge
configureappend.configure

All six are plain booleans, default-deny, not path-scoped. The asymmetry is deliberate rather than a gap: listing a remote lane needs the recipient's enum key, and shipping that inside a published app "would give every visitor read access to the whole lane."

Two things that are not gates on append, despite appearances. There is no read-only check anywhere in the append handler, sg.app.writable is irrelevant to it, and a read-key session can write to a lane given the grant. And the CSP is not an append rule: the frame ships connect-src blob: data:, so a direct fetch to these endpoints is blocked unless the app declares permissions.network: true, which reopens all egress and is the worse choice. Use the bridge. See the build brief↗, which had both of these wrong until the review corrected it.

The inbox field is the lane id, and today it is the token

A list response labels each entry with an inbox value. That value is the storage folder name, and the folder is named by the raw append token, byte for byte, while config.append_anchors stores sha256(token). So the design hashes the token in config and then writes the plaintext token into the object key.

The disclosure is bounded: list is gated by the enum key, so it reaches only the vault owner, who already holds every credential in play; and the token is a write-only lane address, closer to an email address than a password. The residual risk is storage rather than API, the raw token becomes an object key, so it lands in access logs, inventory reports and backups, "surfaces with a very different audience from the enum-key holder." The team intends to fold the folder name to sha256(token), which is a breaking change needing a migration. Documented here now so that nobody has to discover it from a debrief.

Lanes live at bare/append/{token}/pending/ and …/processed/, outside the version-controlled commit tree: appends never touch a branch and never conflict with a push.

Several senders on one vault

Register several append_anchors and each sender writes into their own lane, distinguished by their token. A listing can be scoped to one lane, so one correspondent flooding you does not bury another, and revoking one sender is removing one anchor, with no effect on the rest.

Limits and codes

LimitValueOn breach
Payload per write5 MB413
Pending files per token1000507
File IDs per batch100400
Inline content when listing3 MB cumulative413
Page size50 default, 200 maxclamped silently

The append_token pattern is ^[0-9a-f]{16,128}$, hex only. A prefixed token returns 400, not 403; see errors↗ for why that distinction saves time.

See also


Site index for agents↗ · HTML version↗