@4xeoz/re-entry 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +337 -0
  2. package/node_modules/@webmcp-challenge/reentry-core/README.md +112 -0
  3. package/node_modules/@webmcp-challenge/reentry-core/package.json +38 -0
  4. package/node_modules/@webmcp-challenge/reentry-core/protocol/test-vectors/v0.1.json +47 -0
  5. package/node_modules/@webmcp-challenge/reentry-core/src/agent-adapter.mjs +438 -0
  6. package/node_modules/@webmcp-challenge/reentry-core/src/cloud-receiver-http.mjs +268 -0
  7. package/node_modules/@webmcp-challenge/reentry-core/src/host-sdk.mjs +278 -0
  8. package/node_modules/@webmcp-challenge/reentry-core/src/index.mjs +3 -0
  9. package/node_modules/@webmcp-challenge/reentry-core/src/local-connector-client.mjs +530 -0
  10. package/node_modules/@webmcp-challenge/reentry-core/src/managed-context-adapter.mjs +275 -0
  11. package/node_modules/@webmcp-challenge/reentry-core/src/protocol.mjs +845 -0
  12. package/node_modules/@webmcp-challenge/reentry-core/src/receiver-core.mjs +867 -0
  13. package/node_modules/@webmcp-challenge/reentry-core/src/receiver-delivery.mjs +613 -0
  14. package/node_modules/@webmcp-challenge/reentry-core/src/receiver-http-contract.mjs +24 -0
  15. package/node_modules/@webmcp-challenge/reentry-core/src/receiver-support.mjs +151 -0
  16. package/node_modules/@webmcp-challenge/reentry-core/src/sqlite-receiver-schema.mjs +184 -0
  17. package/node_modules/@webmcp-challenge/reentry-core/src/sqlite-receiver-store.mjs +573 -0
  18. package/package.json +44 -0
  19. package/src/browser-prompt.mjs +18 -0
  20. package/src/codex-discovery.mjs +246 -0
  21. package/src/codex-exec-adapter.mjs +197 -0
  22. package/src/codex-queue-adapter.mjs +214 -0
  23. package/src/credentials.mjs +87 -0
  24. package/src/index.mjs +6 -0
  25. package/src/local-connector.mjs +82 -0
  26. package/src/macos-service.mjs +184 -0
  27. package/src/main.mjs +733 -0
  28. package/src/pairing-client.mjs +545 -0
  29. package/src/terminal-ui.mjs +99 -0
@@ -0,0 +1,151 @@
1
+ const IDENTIFIER_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$/;
2
+ const MAX_OPAQUE_TOKEN_BYTES = 4 * 1_024;
3
+
4
+ export function requireExactInput(value, allowedFields, requiredFields, label) {
5
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6
+ throw validation("receiver_input_invalid", `${label} must be an object`);
7
+ }
8
+ const prototype = Object.getPrototypeOf(value);
9
+ if (prototype !== Object.prototype && prototype !== null) {
10
+ throw validation("receiver_input_invalid", `${label} must be a plain object`);
11
+ }
12
+ for (const key of Reflect.ownKeys(value)) {
13
+ if (typeof key === "symbol") {
14
+ throw validation("receiver_input_invalid", `${label} cannot contain symbol properties`);
15
+ }
16
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
17
+ if (!descriptor?.enumerable || !("value" in descriptor)) {
18
+ throw validation(
19
+ "receiver_input_invalid",
20
+ `${label} must contain enumerable data properties only`,
21
+ );
22
+ }
23
+ }
24
+ const fields = Object.keys(value);
25
+ if (fields.some((field) => !allowedFields.includes(field))) {
26
+ throw validation("receiver_input_fields_invalid", `${label} contains an unsupported field`);
27
+ }
28
+ if (requiredFields.some((field) => !fields.includes(field))) {
29
+ throw validation("receiver_input_fields_invalid", `${label} is missing a required field`);
30
+ }
31
+ }
32
+
33
+ export function requireIdentifier(value, label) {
34
+ if (
35
+ typeof value !== "string" ||
36
+ Buffer.byteLength(value, "utf8") > 160 ||
37
+ !IDENTIFIER_PATTERN.test(value)
38
+ ) {
39
+ throw validation("receiver_identifier_invalid", `${label} is invalid`);
40
+ }
41
+ return value;
42
+ }
43
+
44
+ export function requireOpaqueToken(value, label, code) {
45
+ if (
46
+ typeof value !== "string" ||
47
+ value.length === 0 ||
48
+ Buffer.byteLength(value, "utf8") > MAX_OPAQUE_TOKEN_BYTES ||
49
+ /[^\x21-\x7e]/.test(value)
50
+ ) {
51
+ throw authorization(code, `${label} is invalid`);
52
+ }
53
+ return value;
54
+ }
55
+
56
+ export function requireTimestamp(value, label) {
57
+ if (typeof value !== "string" || value.length > 27) {
58
+ throw validation("receiver_timestamp_invalid", `${label} must be a canonical ISO-8601 timestamp`);
59
+ }
60
+ const parsed = Date.parse(value);
61
+ if (!Number.isFinite(parsed) || new Date(parsed).toISOString() !== value) {
62
+ throw validation("receiver_timestamp_invalid", `${label} must be a canonical ISO-8601 timestamp`);
63
+ }
64
+ return value;
65
+ }
66
+
67
+ export function deepFreeze(value) {
68
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
69
+ for (const child of Object.values(value)) deepFreeze(child);
70
+ Object.freeze(value);
71
+ }
72
+ return value;
73
+ }
74
+
75
+ export class ReceiverValidationError extends Error {
76
+ constructor(code, message, statusCode = 422) {
77
+ super(message);
78
+ this.name = "ReceiverValidationError";
79
+ this.code = code;
80
+ this.statusCode = statusCode;
81
+ }
82
+ }
83
+
84
+ export class ReceiverAuthorizationError extends Error {
85
+ constructor(code, message) {
86
+ super(message);
87
+ this.name = "ReceiverAuthorizationError";
88
+ this.code = code;
89
+ this.statusCode = 403;
90
+ }
91
+ }
92
+
93
+ export class ReceiverConflictError extends Error {
94
+ constructor(code, message, statusCode = 409) {
95
+ super(message);
96
+ this.name = "ReceiverConflictError";
97
+ this.code = code;
98
+ this.statusCode = statusCode;
99
+ }
100
+ }
101
+
102
+ export class ReceiverScopeError extends Error {
103
+ constructor(code, message, statusCode = 422) {
104
+ super(message);
105
+ this.name = "ReceiverScopeError";
106
+ this.code = code;
107
+ this.statusCode = statusCode;
108
+ }
109
+ }
110
+
111
+ export class ReceiverNotFoundError extends Error {
112
+ constructor(code, message) {
113
+ super(message);
114
+ this.name = "ReceiverNotFoundError";
115
+ this.code = code;
116
+ this.statusCode = 404;
117
+ }
118
+ }
119
+
120
+ export class ReceiverInvariantError extends Error {
121
+ constructor(code, message) {
122
+ super(message);
123
+ this.name = "ReceiverInvariantError";
124
+ this.code = code;
125
+ this.statusCode = 500;
126
+ }
127
+ }
128
+
129
+ export function validation(code, message, statusCode) {
130
+ return new ReceiverValidationError(code, message, statusCode);
131
+ }
132
+
133
+ export function authorization(code, message) {
134
+ return new ReceiverAuthorizationError(code, message);
135
+ }
136
+
137
+ export function conflict(code, message, statusCode) {
138
+ return new ReceiverConflictError(code, message, statusCode);
139
+ }
140
+
141
+ export function scope(code, message, statusCode) {
142
+ return new ReceiverScopeError(code, message, statusCode);
143
+ }
144
+
145
+ export function notFound(code, message) {
146
+ return new ReceiverNotFoundError(code, message);
147
+ }
148
+
149
+ export function invariant(code, message) {
150
+ return new ReceiverInvariantError(code, message);
151
+ }
@@ -0,0 +1,184 @@
1
+ export const SCHEMA_VERSION = 2;
2
+
3
+ const BASE_SCHEMA_SQL = `
4
+ CREATE TABLE receiver_challenges (
5
+ challenge_id TEXT PRIMARY KEY,
6
+ manifest_id TEXT NOT NULL UNIQUE,
7
+ manifest_json TEXT NOT NULL,
8
+ expected_origin TEXT NOT NULL,
9
+ effective_expires_at TEXT NOT NULL,
10
+ status TEXT NOT NULL CHECK (status IN ('pending', 'approved', 'declined')),
11
+ decision_id TEXT UNIQUE,
12
+ decision_action TEXT CHECK (decision_action IN ('approve', 'decline')),
13
+ subject_id TEXT,
14
+ created_at TEXT NOT NULL,
15
+ decided_at TEXT,
16
+ CHECK (
17
+ (status = 'pending' AND decision_id IS NULL AND decision_action IS NULL
18
+ AND subject_id IS NULL AND decided_at IS NULL)
19
+ OR
20
+ (status = 'approved' AND decision_id IS NOT NULL AND decision_action = 'approve'
21
+ AND subject_id IS NOT NULL AND decided_at IS NOT NULL)
22
+ OR
23
+ (status = 'declined' AND decision_id IS NOT NULL AND decision_action = 'decline'
24
+ AND subject_id IS NOT NULL AND decided_at IS NOT NULL)
25
+ )
26
+ ) STRICT;
27
+
28
+ CREATE TABLE receiver_grants (
29
+ grant_id TEXT PRIMARY KEY,
30
+ challenge_id TEXT NOT NULL UNIQUE REFERENCES receiver_challenges(challenge_id),
31
+ manifest_id TEXT NOT NULL,
32
+ binding_id TEXT NOT NULL UNIQUE,
33
+ subject_id TEXT NOT NULL,
34
+ delivery_target_id TEXT NOT NULL,
35
+ correlation_id TEXT NOT NULL,
36
+ issuer_origin TEXT NOT NULL,
37
+ workflow_type TEXT NOT NULL,
38
+ workflow_id TEXT NOT NULL,
39
+ event_type TEXT NOT NULL,
40
+ canonical_url TEXT NOT NULL,
41
+ expires_at TEXT NOT NULL,
42
+ human_boundary TEXT NOT NULL,
43
+ runs_remaining INTEGER NOT NULL CHECK (runs_remaining IN (0, 1)),
44
+ revoked_at TEXT,
45
+ receipt_json TEXT NOT NULL,
46
+ created_at TEXT NOT NULL
47
+ ) STRICT;
48
+
49
+ CREATE TABLE receiver_events (
50
+ event_id TEXT PRIMARY KEY,
51
+ grant_id TEXT NOT NULL UNIQUE REFERENCES receiver_grants(grant_id),
52
+ canonical_body TEXT NOT NULL,
53
+ acceptance_json TEXT NOT NULL,
54
+ received_at TEXT NOT NULL
55
+ ) STRICT;
56
+
57
+ CREATE TABLE receiver_deliveries (
58
+ delivery_id TEXT PRIMARY KEY,
59
+ event_id TEXT NOT NULL UNIQUE REFERENCES receiver_events(event_id),
60
+ grant_id TEXT NOT NULL UNIQUE REFERENCES receiver_grants(grant_id),
61
+ delivery_target_id TEXT NOT NULL,
62
+ status TEXT NOT NULL CHECK (status = 'pending'),
63
+ created_at TEXT NOT NULL
64
+ ) STRICT;
65
+
66
+ CREATE INDEX receiver_deliveries_pending
67
+ ON receiver_deliveries(status, delivery_target_id, created_at);
68
+ `;
69
+
70
+ export const DELIVERY_STATE_SCHEMA_SQL = `
71
+ CREATE TABLE receiver_delivery_states (
72
+ delivery_id TEXT PRIMARY KEY REFERENCES receiver_deliveries(delivery_id),
73
+ status TEXT NOT NULL CHECK (
74
+ status IN ('pending', 'leased', 'retry_exhausted', 'acknowledged', 'cancelled')
75
+ ),
76
+ maximum_attempts INTEGER NOT NULL CHECK (maximum_attempts BETWEEN 1 AND 100),
77
+ current_attempt INTEGER NOT NULL CHECK (current_attempt BETWEEN 0 AND 100),
78
+ current_connector_id TEXT,
79
+ current_lease_token_digest TEXT UNIQUE,
80
+ leased_at TEXT,
81
+ lease_expires_at TEXT,
82
+ effect_id TEXT UNIQUE,
83
+ effect_attestation_json TEXT,
84
+ acknowledged_at TEXT,
85
+ terminal_reason TEXT CHECK (
86
+ terminal_reason IS NULL OR terminal_reason IN (
87
+ 'grant_expired', 'grant_revoked', 'attempt_limit_reached'
88
+ )
89
+ ),
90
+ updated_at TEXT NOT NULL,
91
+ CHECK (
92
+ current_attempt <= maximum_attempts
93
+ ),
94
+ CHECK (
95
+ (
96
+ status = 'pending' AND current_attempt = 0 AND current_connector_id IS NULL
97
+ AND current_lease_token_digest IS NULL AND leased_at IS NULL
98
+ AND lease_expires_at IS NULL AND effect_id IS NULL
99
+ AND effect_attestation_json IS NULL AND acknowledged_at IS NULL
100
+ AND terminal_reason IS NULL
101
+ ) OR (
102
+ status = 'leased' AND current_attempt >= 1 AND current_connector_id IS NOT NULL
103
+ AND current_lease_token_digest IS NOT NULL AND leased_at IS NOT NULL
104
+ AND lease_expires_at IS NOT NULL AND effect_id IS NULL
105
+ AND effect_attestation_json IS NULL AND acknowledged_at IS NULL
106
+ AND terminal_reason IS NULL
107
+ ) OR (
108
+ status = 'retry_exhausted' AND current_attempt >= 1
109
+ AND current_connector_id IS NOT NULL AND current_lease_token_digest IS NOT NULL
110
+ AND leased_at IS NOT NULL AND lease_expires_at IS NOT NULL
111
+ AND effect_id IS NULL AND effect_attestation_json IS NULL
112
+ AND acknowledged_at IS NULL AND terminal_reason IS NOT NULL
113
+ ) OR (
114
+ status = 'acknowledged' AND current_attempt >= 1
115
+ AND current_connector_id IS NOT NULL AND current_lease_token_digest IS NOT NULL
116
+ AND leased_at IS NOT NULL AND lease_expires_at IS NOT NULL
117
+ AND effect_id IS NOT NULL AND effect_attestation_json IS NOT NULL
118
+ AND acknowledged_at IS NOT NULL AND terminal_reason IS NULL
119
+ ) OR (
120
+ status = 'cancelled' AND current_attempt = 0 AND current_connector_id IS NULL
121
+ AND current_lease_token_digest IS NULL AND leased_at IS NULL
122
+ AND lease_expires_at IS NULL AND effect_id IS NULL
123
+ AND effect_attestation_json IS NULL AND acknowledged_at IS NULL
124
+ AND terminal_reason IN ('grant_expired', 'grant_revoked')
125
+ )
126
+ )
127
+ ) STRICT;
128
+
129
+ CREATE TABLE receiver_delivery_attempts (
130
+ delivery_id TEXT NOT NULL REFERENCES receiver_deliveries(delivery_id),
131
+ attempt INTEGER NOT NULL CHECK (attempt BETWEEN 1 AND 100),
132
+ connector_id TEXT NOT NULL,
133
+ lease_token_digest TEXT NOT NULL UNIQUE,
134
+ leased_at TEXT NOT NULL,
135
+ lease_expires_at TEXT NOT NULL,
136
+ PRIMARY KEY (delivery_id, attempt)
137
+ ) STRICT;
138
+
139
+ CREATE INDEX receiver_delivery_states_claimable
140
+ ON receiver_delivery_states(status, lease_expires_at, delivery_id);
141
+
142
+ CREATE INDEX receiver_deliveries_target_order
143
+ ON receiver_deliveries(delivery_target_id, created_at, delivery_id);
144
+ `;
145
+
146
+ export const SCHEMA_SQL = `${BASE_SCHEMA_SQL}\n${DELIVERY_STATE_SCHEMA_SQL}`;
147
+
148
+ export const DELIVERY_DETAIL_SELECT = `
149
+ SELECT
150
+ d.delivery_id,
151
+ d.event_id,
152
+ d.grant_id,
153
+ d.delivery_target_id,
154
+ d.created_at,
155
+ s.status,
156
+ s.maximum_attempts,
157
+ s.current_attempt,
158
+ s.current_connector_id,
159
+ s.current_lease_token_digest,
160
+ s.leased_at,
161
+ s.lease_expires_at,
162
+ s.effect_id,
163
+ s.effect_attestation_json,
164
+ s.acknowledged_at,
165
+ s.terminal_reason,
166
+ s.updated_at,
167
+ g.subject_id,
168
+ g.binding_id AS grant_binding_id,
169
+ g.correlation_id,
170
+ g.issuer_origin AS grant_issuer_origin,
171
+ g.workflow_id,
172
+ g.event_type,
173
+ g.canonical_url,
174
+ g.expires_at AS grant_expires_at,
175
+ g.revoked_at AS grant_revoked_at,
176
+ g.human_boundary,
177
+ g.receipt_json,
178
+ e.canonical_body,
179
+ e.received_at
180
+ FROM receiver_deliveries d
181
+ JOIN receiver_delivery_states s ON s.delivery_id = d.delivery_id
182
+ JOIN receiver_grants g ON g.grant_id = d.grant_id
183
+ JOIN receiver_events e ON e.event_id = d.event_id
184
+ `;