@mdbase-dev/connect 0.1.0-beta.94 → 0.1.0-beta.95

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.
@@ -0,0 +1,77 @@
1
+ import type { ContractRequirement, FileAction, JsonObject } from "@mdbase-dev/connect-protocol";
2
+ import type { MdbaseApplicationManifest } from "./application-contract.js";
3
+ import type { MdbaseConnectionInfo } from "./connection-types.js";
4
+ import { type MdbaseEffectiveCapabilities, type MdbaseCapabilityEvidence } from "./capabilities.js";
5
+ import type { MdbaseConnection } from "./connection.js";
6
+ import type { ConnectRequestOptions } from "./operation-types.js";
7
+ type ReadinessPublication = {
8
+ status: "authorization_required";
9
+ } | {
10
+ status: "blocked";
11
+ problem: {
12
+ code: string;
13
+ message: string;
14
+ };
15
+ };
16
+ /** Live verification owns no session state; callers supply identity and cancellation guards. */
17
+ export declare function verifyStructuredReadiness<Frontmatter extends JsonObject>(input: {
18
+ collectionId: string;
19
+ readiness: MdbaseStructuredReadiness;
20
+ contracts: ContractRequirement[];
21
+ connection: MdbaseConnection<Frontmatter>;
22
+ controller: AbortController;
23
+ options?: ConnectRequestOptions;
24
+ requestMs: number | null;
25
+ isCurrent: () => boolean;
26
+ publish: (result: ReadinessPublication) => void;
27
+ }): Promise<boolean>;
28
+ export declare function publishedStructuredReadiness(source: MdbaseStructuredReadiness, status: string, verification?: "cached" | "verified"): MdbaseStructuredReadiness;
29
+ export interface ApplicationSessionContext {
30
+ collectionId: string;
31
+ info: MdbaseConnectionInfo;
32
+ capabilities: MdbaseEffectiveCapabilities;
33
+ /** Present only for semantic contract v2. */
34
+ readiness?: MdbaseStructuredReadiness;
35
+ connections: MdbaseConnectionInfo[];
36
+ }
37
+ export declare function applicationReadinessContext(manifest: MdbaseApplicationManifest, collectionId: string, info: MdbaseConnectionInfo, connections: MdbaseConnectionInfo[]): ApplicationSessionContext;
38
+ export declare function verificationKey(manifest: MdbaseApplicationManifest, collectionId: string): string;
39
+ export declare function verificationValue(manifest: MdbaseApplicationManifest): string;
40
+ export declare function collectionSetupInput(manifest: MdbaseApplicationManifest, applicationId: string, declarationDigest: string, typePackAdoptions?: Record<string, Record<string, string>>): {
41
+ applicationId: string;
42
+ declarationDigest: string;
43
+ requirements: {
44
+ configuration: import("@mdbase-dev/connect-protocol").ConfigurationRequirement[];
45
+ };
46
+ provisions: {
47
+ configuration: import("@mdbase-dev/connect-protocol").ConfigurationProvision[];
48
+ typePacks: import("@mdbase-dev/connect-protocol").TypePackProvision[];
49
+ };
50
+ typePackAdoptions?: Record<string, Record<string, string>> | undefined;
51
+ };
52
+ /** Independent v2 declarations; never legacy capability aliases. */
53
+ export interface MdbaseStructuredReadiness {
54
+ files: {
55
+ state: "not_required" | "available" | "requires_authorization";
56
+ missingRequiredActions: FileAction[];
57
+ missingOptionalActions: FileAction[];
58
+ scopeMatches: boolean;
59
+ evidence: MdbaseCapabilityEvidence[];
60
+ };
61
+ contracts: {
62
+ state: "not_required" | "checking" | "verified" | "requires_setup" | "requires_authorization" | "temporarily_unavailable";
63
+ missing: ContractRequirement[];
64
+ evidence: MdbaseCapabilityEvidence[];
65
+ };
66
+ setup: {
67
+ state: "not_required" | "checking" | "review_required" | "current" | "cached" | "blocked" | "requires_authorization";
68
+ evidence: MdbaseCapabilityEvidence[];
69
+ };
70
+ notifications: {
71
+ state: "not_required" | "requires_registration";
72
+ registration: "unverified";
73
+ evidence: MdbaseCapabilityEvidence[];
74
+ };
75
+ }
76
+ export declare function structuredReadiness(manifest: MdbaseApplicationManifest, info: MdbaseConnectionInfo): MdbaseStructuredReadiness;
77
+ export {};
@@ -0,0 +1,126 @@
1
+ /* The versioned protocol package is the sole capability-to-operation compiler. */
2
+ import { effectiveCapabilities } from "./capabilities.js";
3
+ import { MdbaseConnectError } from "./errors.js";
4
+ import { withRequestBudget } from "./request-budget.js";
5
+ /** Live verification owns no session state; callers supply identity and cancellation guards. */
6
+ export async function verifyStructuredReadiness(input) {
7
+ const { collectionId, readiness, contracts, connection, controller, options, requestMs, isCurrent, publish } = input;
8
+ const abort = () => controller.abort(options?.signal?.reason);
9
+ if (options?.signal?.aborted)
10
+ abort();
11
+ else
12
+ options?.signal?.addEventListener("abort", abort, { once: true });
13
+ try {
14
+ const outcome = await withRequestBudget({ ...options, signal: controller.signal }, requestMs, request => connection.describe(request));
15
+ if (!isCurrent())
16
+ return false;
17
+ if (!outcome.ok) {
18
+ const authorizationRequired = ["access_denied", "collection_access_denied", "insufficient_access", "not_authorized", "authorization_expired", "application_declaration_mismatch"].includes(outcome.problem.code);
19
+ readiness.contracts = { state: authorizationRequired ? "requires_authorization" : "temporarily_unavailable", missing: [], evidence: [{ source: "runtime", fact: outcome.problem.message }] };
20
+ publish(authorizationRequired
21
+ ? { status: "authorization_required" }
22
+ : { status: "blocked", problem: outcome.problem });
23
+ return false;
24
+ }
25
+ if (outcome.value.collectionId !== collectionId) {
26
+ readiness.contracts = { state: "temporarily_unavailable", missing: [], evidence: [] };
27
+ publish({ status: "blocked", problem: { code: "collection_not_ready", message: "Description belongs to a different collection." } });
28
+ return false;
29
+ }
30
+ const missing = contracts.filter(required => !outcome.value.contracts.some(actual => actual.id === required.id && actual.version === required.version && actual.digest === required.digest));
31
+ readiness.contracts = { state: missing.length ? "requires_setup" : "verified", missing,
32
+ evidence: [{ source: "authority", fact: "Exact contract ID, version and digest checked by live describe for this collection." }] };
33
+ if (missing.length) {
34
+ publish({ status: "blocked", problem: { code: "collection_not_ready", message: "The collection is missing required exact contracts." } });
35
+ return false;
36
+ }
37
+ }
38
+ catch (error) {
39
+ if (!isCurrent())
40
+ return false;
41
+ if (!(error instanceof MdbaseConnectError))
42
+ throw error;
43
+ readiness.contracts = { state: "temporarily_unavailable", missing: [], evidence: [{ source: "runtime", fact: error.problem.message }] };
44
+ publish({ status: "blocked", problem: error.problem });
45
+ return false;
46
+ }
47
+ finally {
48
+ options?.signal?.removeEventListener("abort", abort);
49
+ }
50
+ return true;
51
+ }
52
+ export function publishedStructuredReadiness(source, status, verification) {
53
+ const readiness = structuredClone(source);
54
+ if (readiness.setup.state !== "not_required" && readiness.setup.state !== "current") {
55
+ readiness.setup.state = status === "ready" ? (verification === "cached" ? "cached" : "current")
56
+ : status === "setup_review_required" ? "review_required"
57
+ : status === "authorization_required" ? "requires_authorization"
58
+ : status === "blocked" ? "blocked" : "checking";
59
+ readiness.setup.evidence = [{ source: status === "ready" && verification === "cached" ? "runtime" : "authority",
60
+ fact: `Collection setup verification: ${readiness.setup.state}.` }];
61
+ }
62
+ return readiness;
63
+ }
64
+ export function applicationReadinessContext(manifest, collectionId, info, connections) {
65
+ return {
66
+ collectionId, info,
67
+ capabilities: effectiveCapabilities(manifest.requirements.capabilities, manifest, info),
68
+ ...(manifest.requirements?.capabilities?.contract_version === 2
69
+ ? { readiness: structuredReadiness(manifest, info) } : {}),
70
+ connections
71
+ };
72
+ }
73
+ export function verificationKey(manifest, collectionId) {
74
+ return `mdbase-application-session:v1:${manifest.id}:${collectionId}`;
75
+ }
76
+ export function verificationValue(manifest) {
77
+ return JSON.stringify({
78
+ capabilities: manifest.requirements?.capabilities,
79
+ requirements: manifest.requirements?.configuration ?? [],
80
+ provisions: manifest.provisions ?? {}
81
+ });
82
+ }
83
+ export function collectionSetupInput(manifest, applicationId, declarationDigest, typePackAdoptions) {
84
+ return {
85
+ applicationId, declarationDigest,
86
+ requirements: { configuration: manifest.requirements?.configuration ?? [] },
87
+ provisions: {
88
+ configuration: manifest.provisions?.configuration ?? [],
89
+ typePacks: manifest.provisions?.type_packs ?? []
90
+ },
91
+ ...(typePackAdoptions ? { typePackAdoptions } : {})
92
+ };
93
+ }
94
+ function sameScope(left, right) {
95
+ if (!right || left.kind !== right.kind)
96
+ return false;
97
+ if (left.kind === "collection" || right.kind === "collection")
98
+ return true;
99
+ const a = [...new Set(left.folders)].sort();
100
+ const b = [...new Set(right.folders)].sort();
101
+ return JSON.stringify(a) === JSON.stringify(b);
102
+ }
103
+ export function structuredReadiness(manifest, info) {
104
+ const files = manifest.requirements?.files;
105
+ const requirement = files && "required" in files ? files : undefined;
106
+ const scopeMatches = !requirement || sameScope(requirement.scope, info.fileCapability?.scope);
107
+ const missing = (actions) => actions.filter(action => !scopeMatches || !info.fileCapability?.actions.includes(action));
108
+ const missingRequiredActions = missing(requirement?.required ?? []);
109
+ const missingOptionalActions = missing(requirement?.optional ?? []);
110
+ const contracts = manifest.requirements?.contracts ?? [];
111
+ const setup = (manifest.provisions?.type_packs.length ?? 0) > 0 || (manifest.provisions?.configuration?.length ?? 0) > 0;
112
+ return {
113
+ files: {
114
+ state: !requirement ? "not_required" : missingRequiredActions.length ? "requires_authorization" : "available",
115
+ missingRequiredActions, missingOptionalActions, scopeMatches,
116
+ evidence: [{ source: "authorization", fact: "Compared exact file actions and folder scope with connection.info().fileCapability." }]
117
+ },
118
+ contracts: { state: contracts.length ? "checking" : "not_required", missing: [], evidence: [] },
119
+ setup: { state: setup ? "checking" : "not_required", evidence: [] },
120
+ notifications: {
121
+ state: manifest.notifications?.criteria.length ? "requires_registration" : "not_required",
122
+ registration: "unverified",
123
+ evidence: [{ source: "runtime", fact: "The connection API exposes registration commands but no current delivery-registration query. Manifest criteria do not prove approval or delivery registration." }]
124
+ }
125
+ };
126
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mdbase-dev/connect",
3
- "version": "0.1.0-beta.94",
3
+ "version": "0.1.0-beta.95",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -33,7 +33,7 @@
33
33
  "README.md"
34
34
  ],
35
35
  "dependencies": {
36
- "@mdbase-dev/connect-protocol": "0.1.0-beta.94"
36
+ "@mdbase-dev/connect-protocol": "0.1.0-beta.95"
37
37
  },
38
38
  "devDependencies": {
39
39
  "esbuild": "^0.28.1",