Manifest: what virta installs
A service-compris host learns what virta needs from one declarative
manifest, installed once by someone holding the configurator role
(tosijs-platform#5). It declares a single collection, virta:event: the
append-only log every board and agent folds. There is no task collection
— current task state is a view over the events, never stored.
{
manifest: 1, name: 'virta', version: '<virta version>',
collections: {
'virta:event': {
schema: <the event: id, taskId, at, by, kind, payload; closed>,
envelope: { seq: true, requireAttribution: true },
access: [
{ role: 'author', read: 'ALL', list: 'ALL', write: 'ALL' },
{ role: 'editor', read: 'ALL', list: 'ALL', write: 'ALL' },
],
},
},
usesRoles: ['author', 'editor'],
}
Names are namespaced by library (virta: — the separator is :), so two
installed libraries wanting an event collection cannot collide, and the
manifest may only declare names in its own namespace. Installing again with
the same version and content is a no-op; a changed schema is a new version;
a new capability declaration needs a second POST with approving.
Version history: 0.1.0 closed the schema and the beta.1 host refused every write (its envelope stamps tripped the schema, tosijs-platform#16); 0.1.1 opened it as the interim; 0.1.2 closes it again on beta.2 and opts into the sequence and attribution.
What the manifest deliberately does not say:
- No
unique: ['id']. The document's path is its id (virta:event/<id>), so an upsert cannot collide; a unique constraint would only add a privileged read to every write. - No
immutable, yet. The client's push is an upsert commit: an identical body is a no-op (the retry case), and the client never resends an id it holds with a different body. The host still would replace a changed body and re-sequence it — tosijs-platform#25 asks for identical → no-op, different → refused. Until it lands, the guard is on our side. - No server-stamped
by.derive: [{ op: 'principal', to: 'by' }]would make provenance unforgeable, which is the design's intent, but it would also overwrite the historical author on an imported GitHub issue. The right home is the envelope's author field (tosijs-platform gap analysis), where the caller'sbyand the token's identity can both live. - No
seqorbyfrom the caller's side of the envelope. The host assigns_seqat commit and stamps_byfrom the credential; a caller cannot send either.envelope: { seq: true }opts the collection into the total order a log needs (writes serialise, about one commit a second — an event log is inside that);requireAttribution: truerefuses a write the host cannot attribute, so_byis always there.