diff --git a/services/ontology/schemas/availabilityStatus.json b/services/ontology/schemas/availabilityStatus.json new file mode 100644 index 000000000..832a87246 --- /dev/null +++ b/services/ontology/schemas/availabilityStatus.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "47478875-c0cf-4b62-97b3-5b0b62d7f491", + "title": "AvailabilityStatus", + "type": "object", + "description": "A person's self-declared availability ('do not disturb', busy, away), append-only on their OWN vault with a public ACL so any platform can honour it before notifying or calling them. The newest envelope by `since` is the current state; earlier ones are history. `until` makes a state self-expiring; a reader treats an expired state as 'available'. Never written by anyone but the owner.", + "properties": { + "statusId": { "type": "string", "description": "Body id of this status entry" }, + "ownerEName": { "type": "string", "description": "@-prefixed eName of the person the status belongs to" }, + "state": { "type": "string", "enum": ["available", "dnd", "busy", "away"] }, + "since": { "type": "string", "format": "date-time", "description": "When this state began; newest `since` wins" }, + "updatedAt": { "type": "string", "format": "date-time" }, + "until": { "type": "string", "format": "date-time", "description": "Optional self-expiry; past it the person is available again" }, + "note": { "type": "string", "description": "Optional human note shown next to the state" }, + "autoReply": { "type": "string", "description": "Optional text a platform may send back when someone @-mentions the owner while unavailable" } + }, + "required": ["statusId", "ownerEName", "state", "since"], + "additionalProperties": true +} diff --git a/services/ontology/schemas/chatPreference.json b/services/ontology/schemas/chatPreference.json new file mode 100644 index 000000000..87217bf6c --- /dev/null +++ b/services/ontology/schemas/chatPreference.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "eb69c8ad-fec0-4b74-8727-3acd17f34f1b", + "title": "ChatPreference", + "type": "object", + "description": "One person's per-chat viewing preferences — mute, archive, pin — stored on THEIR OWN vault (ACL = self), NOT on the chat: whether I muted a conversation is my data, not the group's, and it must follow me across devices and across W3DS messengers. Keyed by `chatId` (the CANONICAL chat id); at most one envelope per (owner, chatId). Absent fields mean 'no preference', not 'off'.", + "properties": { + "id": { "type": "string", "description": "Body id" }, + "chatId": { "type": "string", "description": "Canonical Chat metaEnvelope id the preference applies to" }, + "updatedAt": { "type": "string", "format": "date-time" }, + "muted": { "type": "boolean", "description": "Suppress notifications from this chat (an @-mention may still pierce)" }, + "archived": { "type": "boolean", "description": "Hide from the main list; never deletes anything" }, + "pinned": { "type": "boolean", "description": "Float the chat to the top of the owner's list" }, + "pinnedAt": { "type": "string", "format": "date-time", "description": "When pinned — orders multiple pinned chats" } + }, + "required": ["id", "chatId", "updatedAt"], + "additionalProperties": true +} diff --git a/services/ontology/schemas/draftMessage.json b/services/ontology/schemas/draftMessage.json new file mode 100644 index 000000000..485385f6c --- /dev/null +++ b/services/ontology/schemas/draftMessage.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "55606983-2744-4d77-9200-b609029a4b3d", + "title": "DraftMessage", + "type": "object", + "description": "An unsent composer draft, on the AUTHOR's own vault (ACL = self), so a message started on one device can be finished on another. At most one draft per (owner, chatId); an empty `text` means the draft is cleared. Reply/edit context is REPLACED wholesale on every write, never merged — otherwise stale context outlives the draft that carried it. A consumer must never let a synced draft overwrite text the person is typing right now: an empty local composer adopts the draft, a non-empty one wins.", + "properties": { + "id": { "type": "string", "description": "Body id" }, + "chatId": { "type": "string", "description": "Canonical Chat id the draft belongs to" }, + "authorEName": { "type": "string", "description": "@-prefixed owner of the draft" }, + "text": { "type": "string", "description": "The draft text; empty = cleared" }, + "updatedAt": { "type": "string", "format": "date-time", "description": "Newest wins across devices" }, + "deviceId": { "type": "string", "description": "Which device last wrote it — lets a device skip echoes of its own writes" }, + "replyToId": { "type": "string", "description": "Message being replied to, if the draft is a reply" }, + "editingId": { "type": "string", "description": "Message being edited, if the draft is an edit" } + }, + "required": ["id", "chatId", "authorEName", "text", "updatedAt"], + "additionalProperties": true +} diff --git a/services/ontology/schemas/fileContext.json b/services/ontology/schemas/fileContext.json new file mode 100644 index 000000000..0793d0681 --- /dev/null +++ b/services/ontology/schemas/fileContext.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "b65218b4-62fb-44ea-b2f6-ffb34d83a629", + "title": "FileContext", + "type": "object", + "description": "An m:n join between a File and a context it appears in (a chat message, a task, a post): `fileRef` and `contextRef` are w3ds envelope URIs. Exists because the same File can be referenced by many contexts and a context can carry many files, while neither side should embed the other. Written by the platform that placed the file into the context; public ACL so any platform can answer 'where has this file been used'.", + "properties": { + "fileRef": { "type": "string", "description": "w3ds://file?id=@vault/ — the File being placed" }, + "contextRef": { "type": "string", "description": "w3ds://envelope?id=@vault/ — where it was placed" }, + "kind": { "type": "string", "description": "The context's nature: 'message', 'task', 'post', …" } + }, + "required": ["fileRef", "contextRef", "kind"], + "additionalProperties": true +} diff --git a/services/ontology/schemas/preferredHandlers.json b/services/ontology/schemas/preferredHandlers.json new file mode 100644 index 000000000..2819b26e7 --- /dev/null +++ b/services/ontology/schemas/preferredHandlers.json @@ -0,0 +1,26 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "9a1b2c3d-4e5f-4a60-8b1c-1122334455ff", + "title": "PreferredHandlers", + "type": "object", + "description": "One person's choice of which platform opens which ontology — the W3DS analogue of OS default apps, on their OWN vault (ACL = self). Keyed by ontology schemaId: `handlers[] = {openUrl, platform?}` where `openUrl` is a template another platform may navigate to when the person taps an envelope of that ontology. One envelope per owner; writes merge one key at a time.", + "properties": { + "id": { "type": "string", "description": "Body id" }, + "type": { "type": "string", "const": "preferred-handlers" }, + "handlers": { + "type": "object", + "description": "schemaId → {openUrl, platform?}", + "additionalProperties": { + "type": "object", + "properties": { + "openUrl": { "type": "string", "description": "URL template that opens this ontology in the chosen platform" }, + "platform": { "type": "string", "description": "Human label of the chosen platform (informational)" } + }, + "required": ["openUrl"] + } + }, + "updatedAt": { "type": "string", "format": "date-time" } + }, + "required": ["id", "type", "handlers", "updatedAt"], + "additionalProperties": true +} diff --git a/services/ontology/schemas/relation.json b/services/ontology/schemas/relation.json new file mode 100644 index 000000000..f27f71dea --- /dev/null +++ b/services/ontology/schemas/relation.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "f9ff8527-f3af-4733-b8df-fa0c97ba03ff", + "title": "Relation", + "type": "object", + "description": "A reified triple: `subject —predicate→ object`, authored by a person and stored on THEIR vault. One ontology for every lightweight edge between envelopes — a reaction (predicate 'react', value '👍'), a pin (predicate 'pin', value 'me'|'all'), a mention notification, a response to an activity (predicate 'respond') — instead of one bespoke ontology per edge kind. `object` is a w3ds envelope URI so the edge survives relocation. Distinct from the registered `Reference` ontology (c20e9437-…), which is a review/score OF a target; a Relation is a statement BETWEEN two envelopes. A cross-vault copy uses the reference mixin (isReference + canonicalOwnerEName + canonicalRelationId): the source-of-truth edge stays on the author's vault.", + "properties": { + "id": { "type": "string", "description": "Body id (mirrors the metaEnvelope id on the canonical)" }, + "subject": { "type": "string", "description": "Who/what the statement is about — an eName or a w3ds envelope URI" }, + "predicate": { "type": "string", "description": "The edge kind: 'react', 'pin', 'respond', 'mention', …" }, + "object": { "type": "string", "description": "Target envelope, as `w3ds://envelope?id=@vault/`" }, + "value": { "type": "string", "description": "Predicate-specific payload: the emoji for 'react', 'me'|'all' for 'pin'" }, + "authorId": { "type": "string", "description": "@-prefixed eName of whoever asserted the relation" }, + "createdAt": { "type": "string", "format": "date-time" }, + "isReference": { "type": "boolean", "description": "True on a cross-vault copy pointing at the canonical" }, + "canonicalOwnerEName": { "type": "string", "description": "Reference mixin: whose vault holds the canonical" }, + "canonicalRelationId": { "type": "string", "description": "Reference mixin: metaEnvelope id of the canonical" }, + "sharedBy": { "type": "string", "description": "Reference mixin: who fanned the copy out" }, + "sharedAt": { "type": "string", "format": "date-time" } + }, + "required": ["id", "predicate", "authorId"], + "additionalProperties": true +} diff --git a/services/ontology/schemas/summary.json b/services/ontology/schemas/summary.json new file mode 100644 index 000000000..210ae786e --- /dev/null +++ b/services/ontology/schemas/summary.json @@ -0,0 +1,38 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "5b1a2c3d-6e7f-4a80-9b1c-2d3e4f5a6b7c", + "title": "Summary", + "type": "object", + "description": "A generated summary of a bounded subject — a call, or a day of conversation — stored ONCE on the subject's vault (the chat/group vault for a call, the group vault for a day digest) rather than recomputed per reader. `subject` names what is summarised; `actionItems`/`events` are structured extractions any platform may render or turn into Tasks/CalendarEvents. Cross-vault copies use the reference mixin (isReference + canonicalOwnerEName + canonicalSummaryId) — the canonical is never duplicated.", + "properties": { + "id": { "type": "string", "description": "Body id" }, + "type": { "type": "string", "const": "summary" }, + "subject": { + "type": "object", + "description": "What is summarised: {kind: 'call'|'day', chatId?, callId?, dayKey?, ref?} — `ref` is a w3ds envelope URI of the source", + "properties": { + "kind": { "type": "string" }, + "chatId": { "type": "string" }, + "callId": { "type": "string" }, + "dayKey": { "type": "string", "description": "YYYY-MM-DD for a day digest" }, + "ref": { "type": "string" } + } + }, + "summaryLine": { "type": "string", "description": "One-line headline" }, + "summary": { "type": "string", "description": "The full summary text" }, + "actionItems": { "type": "array", "items": { "type": "object" }, "description": "Structured to-dos extracted from the subject" }, + "events": { "type": "array", "items": { "type": "object" }, "description": "Structured calendar-shaped extractions" }, + "startedAt": { "type": "string", "format": "date-time", "description": "When the summarised call actually started" }, + "endedAt": { "type": "string", "format": "date-time" }, + "durationSeconds": { "type": "number" }, + "generatedBy": { "type": "string", "description": "@-prefixed eName on whose behalf the summary was generated" }, + "generatedAt": { "type": "string", "format": "date-time" }, + "isReference": { "type": "boolean" }, + "canonicalOwnerEName": { "type": "string" }, + "canonicalSummaryId": { "type": "string" }, + "sharedBy": { "type": "string" }, + "sharedAt": { "type": "string", "format": "date-time" } + }, + "required": ["id", "type", "subject"], + "additionalProperties": true +}