Implement durable typed journals, subscriptions, and Reader document connections
Add checked native journal/subscription bindings, managed-reference retention, bounded history and backpressure, atomic delivery receipts, and fenced hosting. Preserve source publication prediction and replica reconciliation; subscription attachment, controls, and delivery remain authoritative in this initial version. Connect independent manual/Gutenberg document producers to Reader bookshelves through typed adapters. Add connection inspection, shared provider selection, authoring documentation, and restart/rejection/fan-out integration coverage. Verified compiler suite (287 passed, two existing skips), Nix runtime and PostgreSQL qualification, five example assemblies, headless Reader integration, Chromium Reader integration, resource pins, formatting, and lint. No pinned workspace runtime was deployed.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -81,79 +81,81 @@ REVISION=80
|
||||
SEMANTIC_MAJOR=81
|
||||
ON_DELETE=82
|
||||
LIFECYCLE=83
|
||||
RETAIN_OTHER=84
|
||||
KEYED=85
|
||||
PUBLIC_TRAVERSAL=86
|
||||
ID=87
|
||||
DOC=88
|
||||
MODE=89
|
||||
EMITS=90
|
||||
RECEIVER=91
|
||||
REQUIRES=92
|
||||
ANY=93
|
||||
GET=94
|
||||
SET=95
|
||||
WATCH=96
|
||||
START=97
|
||||
STOP=98
|
||||
READ=99
|
||||
WRITE=100
|
||||
RESOLVE=101
|
||||
CONNECT=102
|
||||
DISCONNECT=103
|
||||
CALL=104
|
||||
WATCH_START=105
|
||||
WATCH_STOP=106
|
||||
SUBSCRIBE=107
|
||||
UNSUBSCRIBE=108
|
||||
REGISTER=109
|
||||
CRDT=110
|
||||
OPTIONAL_ONE=111
|
||||
EXACTLY_ONE=112
|
||||
MANY_UNIQUE=113
|
||||
MANY=114
|
||||
ORDERED=115
|
||||
UNIT=116
|
||||
WATCH_HANDLE=117
|
||||
MESSAGE=118
|
||||
ATOM_REF=119
|
||||
INTERFACE_REF=120
|
||||
OPTIONAL=121
|
||||
LIST=122
|
||||
RECORD=123
|
||||
BOOL=124
|
||||
BYTES=125
|
||||
DOUBLE=126
|
||||
INT32=127
|
||||
INT64=128
|
||||
STRING=129
|
||||
UINT32=130
|
||||
UINT64=131
|
||||
TRUE=132
|
||||
FALSE=133
|
||||
NULL=134
|
||||
ARROW=135
|
||||
COLON=136
|
||||
SEMI=137
|
||||
COMMA=138
|
||||
DOT=139
|
||||
LBRACE=140
|
||||
RBRACE=141
|
||||
LBRACK=142
|
||||
RBRACK=143
|
||||
LPAREN=144
|
||||
RPAREN=145
|
||||
LT=146
|
||||
GT=147
|
||||
AMP=148
|
||||
EQUAL=149
|
||||
INTEGER=150
|
||||
JSON_NUMBER=151
|
||||
IDENTIFIER=152
|
||||
STRING_LITERAL=153
|
||||
LINE_COMMENT=154
|
||||
BLOCK_COMMENT=155
|
||||
WS=156
|
||||
JOURNAL=84
|
||||
SUBSCRIPTION=85
|
||||
RETAIN_OTHER=86
|
||||
KEYED=87
|
||||
PUBLIC_TRAVERSAL=88
|
||||
ID=89
|
||||
DOC=90
|
||||
MODE=91
|
||||
EMITS=92
|
||||
RECEIVER=93
|
||||
REQUIRES=94
|
||||
ANY=95
|
||||
GET=96
|
||||
SET=97
|
||||
WATCH=98
|
||||
START=99
|
||||
STOP=100
|
||||
READ=101
|
||||
WRITE=102
|
||||
RESOLVE=103
|
||||
CONNECT=104
|
||||
DISCONNECT=105
|
||||
CALL=106
|
||||
WATCH_START=107
|
||||
WATCH_STOP=108
|
||||
SUBSCRIBE=109
|
||||
UNSUBSCRIBE=110
|
||||
REGISTER=111
|
||||
CRDT=112
|
||||
OPTIONAL_ONE=113
|
||||
EXACTLY_ONE=114
|
||||
MANY_UNIQUE=115
|
||||
MANY=116
|
||||
ORDERED=117
|
||||
UNIT=118
|
||||
WATCH_HANDLE=119
|
||||
MESSAGE=120
|
||||
ATOM_REF=121
|
||||
INTERFACE_REF=122
|
||||
OPTIONAL=123
|
||||
LIST=124
|
||||
RECORD=125
|
||||
BOOL=126
|
||||
BYTES=127
|
||||
DOUBLE=128
|
||||
INT32=129
|
||||
INT64=130
|
||||
STRING=131
|
||||
UINT32=132
|
||||
UINT64=133
|
||||
TRUE=134
|
||||
FALSE=135
|
||||
NULL=136
|
||||
ARROW=137
|
||||
COLON=138
|
||||
SEMI=139
|
||||
COMMA=140
|
||||
DOT=141
|
||||
LBRACE=142
|
||||
RBRACE=143
|
||||
LBRACK=144
|
||||
RBRACK=145
|
||||
LPAREN=146
|
||||
RPAREN=147
|
||||
LT=148
|
||||
GT=149
|
||||
AMP=150
|
||||
EQUAL=151
|
||||
INTEGER=152
|
||||
JSON_NUMBER=153
|
||||
IDENTIFIER=154
|
||||
STRING_LITERAL=155
|
||||
LINE_COMMENT=156
|
||||
BLOCK_COMMENT=157
|
||||
WS=158
|
||||
'edit'=1
|
||||
'module'=2
|
||||
'contract'=3
|
||||
@@ -237,69 +239,71 @@ WS=156
|
||||
'semantic-major'=81
|
||||
'on-delete'=82
|
||||
'lifecycle'=83
|
||||
'retain-other'=84
|
||||
'keyed'=85
|
||||
'public-traversal'=86
|
||||
'id'=87
|
||||
'doc'=88
|
||||
'mode'=89
|
||||
'emits'=90
|
||||
'receiver'=91
|
||||
'requires'=92
|
||||
'any'=93
|
||||
'get'=94
|
||||
'set'=95
|
||||
'watch'=96
|
||||
'start'=97
|
||||
'stop'=98
|
||||
'read'=99
|
||||
'write'=100
|
||||
'resolve'=101
|
||||
'connect'=102
|
||||
'disconnect'=103
|
||||
'call'=104
|
||||
'watch-start'=105
|
||||
'watch-stop'=106
|
||||
'subscribe'=107
|
||||
'unsubscribe'=108
|
||||
'register'=109
|
||||
'crdt'=110
|
||||
'optional-one'=111
|
||||
'exactly-one'=112
|
||||
'many-unique'=113
|
||||
'many'=114
|
||||
'ordered'=115
|
||||
'unit'=116
|
||||
'watch-handle'=117
|
||||
'message'=118
|
||||
'atom-ref'=119
|
||||
'interface-ref'=120
|
||||
'optional'=121
|
||||
'list'=122
|
||||
'record'=123
|
||||
'bool'=124
|
||||
'bytes'=125
|
||||
'double'=126
|
||||
'int32'=127
|
||||
'int64'=128
|
||||
'string'=129
|
||||
'uint32'=130
|
||||
'uint64'=131
|
||||
'true'=132
|
||||
'false'=133
|
||||
'null'=134
|
||||
'->'=135
|
||||
':'=136
|
||||
';'=137
|
||||
','=138
|
||||
'.'=139
|
||||
'{'=140
|
||||
'}'=141
|
||||
'['=142
|
||||
']'=143
|
||||
'('=144
|
||||
')'=145
|
||||
'<'=146
|
||||
'>'=147
|
||||
'&'=148
|
||||
'='=149
|
||||
'journal'=84
|
||||
'subscription'=85
|
||||
'retain-other'=86
|
||||
'keyed'=87
|
||||
'public-traversal'=88
|
||||
'id'=89
|
||||
'doc'=90
|
||||
'mode'=91
|
||||
'emits'=92
|
||||
'receiver'=93
|
||||
'requires'=94
|
||||
'any'=95
|
||||
'get'=96
|
||||
'set'=97
|
||||
'watch'=98
|
||||
'start'=99
|
||||
'stop'=100
|
||||
'read'=101
|
||||
'write'=102
|
||||
'resolve'=103
|
||||
'connect'=104
|
||||
'disconnect'=105
|
||||
'call'=106
|
||||
'watch-start'=107
|
||||
'watch-stop'=108
|
||||
'subscribe'=109
|
||||
'unsubscribe'=110
|
||||
'register'=111
|
||||
'crdt'=112
|
||||
'optional-one'=113
|
||||
'exactly-one'=114
|
||||
'many-unique'=115
|
||||
'many'=116
|
||||
'ordered'=117
|
||||
'unit'=118
|
||||
'watch-handle'=119
|
||||
'message'=120
|
||||
'atom-ref'=121
|
||||
'interface-ref'=122
|
||||
'optional'=123
|
||||
'list'=124
|
||||
'record'=125
|
||||
'bool'=126
|
||||
'bytes'=127
|
||||
'double'=128
|
||||
'int32'=129
|
||||
'int64'=130
|
||||
'string'=131
|
||||
'uint32'=132
|
||||
'uint64'=133
|
||||
'true'=134
|
||||
'false'=135
|
||||
'null'=136
|
||||
'->'=137
|
||||
':'=138
|
||||
';'=139
|
||||
','=140
|
||||
'.'=141
|
||||
'{'=142
|
||||
'}'=143
|
||||
'['=144
|
||||
']'=145
|
||||
'('=146
|
||||
')'=147
|
||||
'<'=148
|
||||
'>'=149
|
||||
'&'=150
|
||||
'='=151
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -81,79 +81,81 @@ REVISION=80
|
||||
SEMANTIC_MAJOR=81
|
||||
ON_DELETE=82
|
||||
LIFECYCLE=83
|
||||
RETAIN_OTHER=84
|
||||
KEYED=85
|
||||
PUBLIC_TRAVERSAL=86
|
||||
ID=87
|
||||
DOC=88
|
||||
MODE=89
|
||||
EMITS=90
|
||||
RECEIVER=91
|
||||
REQUIRES=92
|
||||
ANY=93
|
||||
GET=94
|
||||
SET=95
|
||||
WATCH=96
|
||||
START=97
|
||||
STOP=98
|
||||
READ=99
|
||||
WRITE=100
|
||||
RESOLVE=101
|
||||
CONNECT=102
|
||||
DISCONNECT=103
|
||||
CALL=104
|
||||
WATCH_START=105
|
||||
WATCH_STOP=106
|
||||
SUBSCRIBE=107
|
||||
UNSUBSCRIBE=108
|
||||
REGISTER=109
|
||||
CRDT=110
|
||||
OPTIONAL_ONE=111
|
||||
EXACTLY_ONE=112
|
||||
MANY_UNIQUE=113
|
||||
MANY=114
|
||||
ORDERED=115
|
||||
UNIT=116
|
||||
WATCH_HANDLE=117
|
||||
MESSAGE=118
|
||||
ATOM_REF=119
|
||||
INTERFACE_REF=120
|
||||
OPTIONAL=121
|
||||
LIST=122
|
||||
RECORD=123
|
||||
BOOL=124
|
||||
BYTES=125
|
||||
DOUBLE=126
|
||||
INT32=127
|
||||
INT64=128
|
||||
STRING=129
|
||||
UINT32=130
|
||||
UINT64=131
|
||||
TRUE=132
|
||||
FALSE=133
|
||||
NULL=134
|
||||
ARROW=135
|
||||
COLON=136
|
||||
SEMI=137
|
||||
COMMA=138
|
||||
DOT=139
|
||||
LBRACE=140
|
||||
RBRACE=141
|
||||
LBRACK=142
|
||||
RBRACK=143
|
||||
LPAREN=144
|
||||
RPAREN=145
|
||||
LT=146
|
||||
GT=147
|
||||
AMP=148
|
||||
EQUAL=149
|
||||
INTEGER=150
|
||||
JSON_NUMBER=151
|
||||
IDENTIFIER=152
|
||||
STRING_LITERAL=153
|
||||
LINE_COMMENT=154
|
||||
BLOCK_COMMENT=155
|
||||
WS=156
|
||||
JOURNAL=84
|
||||
SUBSCRIPTION=85
|
||||
RETAIN_OTHER=86
|
||||
KEYED=87
|
||||
PUBLIC_TRAVERSAL=88
|
||||
ID=89
|
||||
DOC=90
|
||||
MODE=91
|
||||
EMITS=92
|
||||
RECEIVER=93
|
||||
REQUIRES=94
|
||||
ANY=95
|
||||
GET=96
|
||||
SET=97
|
||||
WATCH=98
|
||||
START=99
|
||||
STOP=100
|
||||
READ=101
|
||||
WRITE=102
|
||||
RESOLVE=103
|
||||
CONNECT=104
|
||||
DISCONNECT=105
|
||||
CALL=106
|
||||
WATCH_START=107
|
||||
WATCH_STOP=108
|
||||
SUBSCRIBE=109
|
||||
UNSUBSCRIBE=110
|
||||
REGISTER=111
|
||||
CRDT=112
|
||||
OPTIONAL_ONE=113
|
||||
EXACTLY_ONE=114
|
||||
MANY_UNIQUE=115
|
||||
MANY=116
|
||||
ORDERED=117
|
||||
UNIT=118
|
||||
WATCH_HANDLE=119
|
||||
MESSAGE=120
|
||||
ATOM_REF=121
|
||||
INTERFACE_REF=122
|
||||
OPTIONAL=123
|
||||
LIST=124
|
||||
RECORD=125
|
||||
BOOL=126
|
||||
BYTES=127
|
||||
DOUBLE=128
|
||||
INT32=129
|
||||
INT64=130
|
||||
STRING=131
|
||||
UINT32=132
|
||||
UINT64=133
|
||||
TRUE=134
|
||||
FALSE=135
|
||||
NULL=136
|
||||
ARROW=137
|
||||
COLON=138
|
||||
SEMI=139
|
||||
COMMA=140
|
||||
DOT=141
|
||||
LBRACE=142
|
||||
RBRACE=143
|
||||
LBRACK=144
|
||||
RBRACK=145
|
||||
LPAREN=146
|
||||
RPAREN=147
|
||||
LT=148
|
||||
GT=149
|
||||
AMP=150
|
||||
EQUAL=151
|
||||
INTEGER=152
|
||||
JSON_NUMBER=153
|
||||
IDENTIFIER=154
|
||||
STRING_LITERAL=155
|
||||
LINE_COMMENT=156
|
||||
BLOCK_COMMENT=157
|
||||
WS=158
|
||||
'edit'=1
|
||||
'module'=2
|
||||
'contract'=3
|
||||
@@ -237,69 +239,71 @@ WS=156
|
||||
'semantic-major'=81
|
||||
'on-delete'=82
|
||||
'lifecycle'=83
|
||||
'retain-other'=84
|
||||
'keyed'=85
|
||||
'public-traversal'=86
|
||||
'id'=87
|
||||
'doc'=88
|
||||
'mode'=89
|
||||
'emits'=90
|
||||
'receiver'=91
|
||||
'requires'=92
|
||||
'any'=93
|
||||
'get'=94
|
||||
'set'=95
|
||||
'watch'=96
|
||||
'start'=97
|
||||
'stop'=98
|
||||
'read'=99
|
||||
'write'=100
|
||||
'resolve'=101
|
||||
'connect'=102
|
||||
'disconnect'=103
|
||||
'call'=104
|
||||
'watch-start'=105
|
||||
'watch-stop'=106
|
||||
'subscribe'=107
|
||||
'unsubscribe'=108
|
||||
'register'=109
|
||||
'crdt'=110
|
||||
'optional-one'=111
|
||||
'exactly-one'=112
|
||||
'many-unique'=113
|
||||
'many'=114
|
||||
'ordered'=115
|
||||
'unit'=116
|
||||
'watch-handle'=117
|
||||
'message'=118
|
||||
'atom-ref'=119
|
||||
'interface-ref'=120
|
||||
'optional'=121
|
||||
'list'=122
|
||||
'record'=123
|
||||
'bool'=124
|
||||
'bytes'=125
|
||||
'double'=126
|
||||
'int32'=127
|
||||
'int64'=128
|
||||
'string'=129
|
||||
'uint32'=130
|
||||
'uint64'=131
|
||||
'true'=132
|
||||
'false'=133
|
||||
'null'=134
|
||||
'->'=135
|
||||
':'=136
|
||||
';'=137
|
||||
','=138
|
||||
'.'=139
|
||||
'{'=140
|
||||
'}'=141
|
||||
'['=142
|
||||
']'=143
|
||||
'('=144
|
||||
')'=145
|
||||
'<'=146
|
||||
'>'=147
|
||||
'&'=148
|
||||
'='=149
|
||||
'journal'=84
|
||||
'subscription'=85
|
||||
'retain-other'=86
|
||||
'keyed'=87
|
||||
'public-traversal'=88
|
||||
'id'=89
|
||||
'doc'=90
|
||||
'mode'=91
|
||||
'emits'=92
|
||||
'receiver'=93
|
||||
'requires'=94
|
||||
'any'=95
|
||||
'get'=96
|
||||
'set'=97
|
||||
'watch'=98
|
||||
'start'=99
|
||||
'stop'=100
|
||||
'read'=101
|
||||
'write'=102
|
||||
'resolve'=103
|
||||
'connect'=104
|
||||
'disconnect'=105
|
||||
'call'=106
|
||||
'watch-start'=107
|
||||
'watch-stop'=108
|
||||
'subscribe'=109
|
||||
'unsubscribe'=110
|
||||
'register'=111
|
||||
'crdt'=112
|
||||
'optional-one'=113
|
||||
'exactly-one'=114
|
||||
'many-unique'=115
|
||||
'many'=116
|
||||
'ordered'=117
|
||||
'unit'=118
|
||||
'watch-handle'=119
|
||||
'message'=120
|
||||
'atom-ref'=121
|
||||
'interface-ref'=122
|
||||
'optional'=123
|
||||
'list'=124
|
||||
'record'=125
|
||||
'bool'=126
|
||||
'bytes'=127
|
||||
'double'=128
|
||||
'int32'=129
|
||||
'int64'=130
|
||||
'string'=131
|
||||
'uint32'=132
|
||||
'uint64'=133
|
||||
'true'=134
|
||||
'false'=135
|
||||
'null'=136
|
||||
'->'=137
|
||||
':'=138
|
||||
';'=139
|
||||
','=140
|
||||
'.'=141
|
||||
'{'=142
|
||||
'}'=143
|
||||
'['=144
|
||||
']'=145
|
||||
'('=146
|
||||
')'=147
|
||||
'<'=148
|
||||
'>'=149
|
||||
'&'=150
|
||||
'='=151
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1789,10 +1789,14 @@ const lowerState = (state: LoweringState, context: StateDeclContext): StateSlotD
|
||||
valueType: lowerValueType(state, context.valueType()),
|
||||
storagePolicy: policy.REGISTER()
|
||||
? { kind: "register" }
|
||||
: {
|
||||
kind: "crdt-document",
|
||||
updateType: lowerValueType(state, policy.valueType()),
|
||||
},
|
||||
: policy.JOURNAL()
|
||||
? { kind: "journal", limits: JSON.parse(text(policy.jsonObject())) }
|
||||
: policy.SUBSCRIPTION()
|
||||
? { kind: "subscription", payload: lowerValueType(state, policy.valueType()) }
|
||||
: {
|
||||
kind: "crdt-document",
|
||||
updateType: lowerValueType(state, policy.valueType()),
|
||||
},
|
||||
defaultValue,
|
||||
};
|
||||
};
|
||||
@@ -2239,9 +2243,9 @@ const lowerConformanceRule = (state: LoweringState, context: ConformanceDeclCont
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (provider.STATE() || provider.EDGE()) {
|
||||
} else if (provider.STATE() || provider.JOURNAL() || provider.SUBSCRIPTION() || provider.EDGE()) {
|
||||
const name = identifier(provider.identifier(0));
|
||||
const expected = provider.STATE() ? "state" : "edge";
|
||||
const expected = provider.STATE() || provider.JOURNAL() || provider.SUBSCRIPTION() ? "state" : "edge";
|
||||
// Concrete attachments are registered before rules, so unused rules can
|
||||
// also check public traversal without waiting for an application.
|
||||
if (provider.EDGE() && !privateStorage.has(name)) {
|
||||
@@ -2435,6 +2439,74 @@ const lowerConformanceBody = (
|
||||
return [];
|
||||
}
|
||||
const provider = bindingContext.operationProvider();
|
||||
if (provider.SUBSCRIPTION()) {
|
||||
const attachment = requireSymbol(
|
||||
state,
|
||||
state.attachments,
|
||||
identifier(provider.identifier(0)),
|
||||
provider,
|
||||
"attachment",
|
||||
);
|
||||
const primitive = identifier(provider.identifier(1));
|
||||
if (
|
||||
!attachment ||
|
||||
attachment.attachment.kind !== "state" ||
|
||||
attachment.attachment.storagePolicy.kind !== "subscription" ||
|
||||
!["attach", "status", "pause", "resume", "retire"].includes(primitive)
|
||||
) {
|
||||
loweringIssue(
|
||||
state,
|
||||
provider,
|
||||
"invalid-subscription-binding",
|
||||
"Expected native subscription storage and a public subscription primitive",
|
||||
);
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
{
|
||||
operationId,
|
||||
binding: {
|
||||
kind: "subscription",
|
||||
slotId: attachment.attachment.id,
|
||||
primitive: primitive as "attach" | "status" | "pause" | "resume" | "retire",
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
if (provider.JOURNAL()) {
|
||||
const attachment = requireSymbol(
|
||||
state,
|
||||
state.attachments,
|
||||
identifier(provider.identifier(0)),
|
||||
provider,
|
||||
"attachment",
|
||||
);
|
||||
const primitive = identifier(provider.identifier(1));
|
||||
if (
|
||||
!attachment ||
|
||||
attachment.attachment.kind !== "state" ||
|
||||
attachment.attachment.storagePolicy.kind !== "journal" ||
|
||||
!["publish", "readPage", "head"].includes(primitive)
|
||||
) {
|
||||
loweringIssue(
|
||||
state,
|
||||
provider,
|
||||
"invalid-journal-binding",
|
||||
"Expected a native journal and publish, readPage or head",
|
||||
);
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
{
|
||||
operationId,
|
||||
binding: {
|
||||
kind: "journal",
|
||||
slotId: attachment.attachment.id,
|
||||
primitive: primitive as "publish" | "readPage" | "head",
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
if (provider.LIFECYCLE()) {
|
||||
if (identifier(provider.identifier(0)) !== "delete") {
|
||||
loweringIssue(state, provider, "invalid-lifecycle-binding", "Only lifecycle.delete is supported");
|
||||
|
||||
Reference in New Issue
Block a user