@hasna/skills 0.5.2 → 0.5.3

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,14 @@
1
+ import type { RemoteSkillsAuthClient } from "./remote-auth.js";
2
+ import { type RemoteWorkspaceContext } from "./remote-workspace-selection.js";
3
+ import { type InvitationAction, type InvitationInputs, type InvitationResults } from "./remote-invitations.js";
4
+ /** A saved profile constrains explicit input; it never silently supplies another target. */
5
+ export declare function invitationProfileContext(userId: string, membershipId: string, profile?: RemoteWorkspaceContext): Readonly<{
6
+ userId: string;
7
+ membershipId: string;
8
+ }>;
9
+ /** Surface adapters share this dispatch; the remote client owns validation and transport. */
10
+ export declare function invokeFreshInvitation<A extends InvitationAction>(client: RemoteSkillsAuthClient, email: string, code: string, context: RemoteWorkspaceContext, action: A, input: InvitationInputs[A]): Promise<InvitationResults[A]>;
11
+ export declare function invitationCustomerError(error: unknown): {
12
+ code: string;
13
+ error: string;
14
+ };
@@ -0,0 +1,5 @@
1
+ /** Recovery requires an explicit environment URL. Never probe credentials or Keychain to choose its target. */
2
+ export declare function prepareInvitationRecoveryTarget(source?: Record<string, string | undefined>): {
3
+ origin: string;
4
+ unchanged(): void;
5
+ };
@@ -1,3 +1,5 @@
1
+ import { type RequestInvitationEmailChallenge, type AcceptInvitationEmailChallenge } from "./remote-invitation-recovery.js";
2
+ import { type ListRemoteWorkspaceInvitations, type IssueRemoteWorkspaceInvitation, type ResendRemoteWorkspaceInvitation, type RevokeRemoteWorkspaceInvitation, type AcceptRemoteWorkspaceInvitation } from "./remote-invitations.js";
1
3
  import { type LeaveRemoteWorkspace } from "./remote-workspace-leave.js";
2
4
  import { type RemoteWorkspaceContext, type RemoteWorkspaceSession, type RemoteAccountWorkspaceDiscovery } from "./remote-workspace-selection.js";
3
5
  import { type RemoteWorkspaceMembersOptions } from "./remote-workspace.js";
@@ -21,6 +23,8 @@ export declare class HostedApiError extends Error {
21
23
  export declare class RemoteSkillsAuthClient {
22
24
  readonly apiOrigin: string;
23
25
  constructor(apiUrl: string);
26
+ requestInvitationEmailChallenge(input: RequestInvitationEmailChallenge): Promise<import("./remote-invitation-recovery.js").RemoteInvitationEmailChallenge>;
27
+ acceptInvitationEmailChallenge(input: AcceptInvitationEmailChallenge): Promise<import("./remote-invitation-recovery.js").RemoteInvitationEmailAcceptance>;
24
28
  requestCode(email: string): Promise<any>;
25
29
  verifyCode(email: string, code: string): Promise<any>;
26
30
  startDevice(): Promise<any>;
@@ -31,6 +35,14 @@ export declare class RemoteSkillsAuthClient {
31
35
  /** Contains a secret session token. Selection never creates or stores an API key. */
32
36
  switchWorkspace(email: string, code: string, context: RemoteWorkspaceContext): Promise<RemoteWorkspaceSession>;
33
37
  private workspaceLogin;
38
+ listWorkspaceInvitations(email: string, code: string, context: RemoteWorkspaceContext, options?: ListRemoteWorkspaceInvitations): Promise<import("./remote-invitations.js").RemoteWorkspaceInvitationsPage>;
39
+ getWorkspaceInvitation(email: string, code: string, context: RemoteWorkspaceContext, invitationId: string): Promise<{
40
+ invitation: import("./remote-invitations.js").RemoteWorkspaceInvitation;
41
+ }>;
42
+ issueWorkspaceInvitation(email: string, code: string, context: RemoteWorkspaceContext, input: IssueRemoteWorkspaceInvitation): Promise<import("./remote-invitations.js").RemoteWorkspaceInvitationResult>;
43
+ resendWorkspaceInvitation(email: string, code: string, context: RemoteWorkspaceContext, invitationId: string, input: ResendRemoteWorkspaceInvitation): Promise<import("./remote-invitations.js").RemoteWorkspaceInvitationResult>;
44
+ revokeWorkspaceInvitation(email: string, code: string, context: RemoteWorkspaceContext, invitationId: string, input: RevokeRemoteWorkspaceInvitation): Promise<import("./remote-invitations.js").RemoteWorkspaceInvitationResult>;
45
+ acceptWorkspaceInvitation(email: string, code: string, context: RemoteWorkspaceContext, invitationId: string, input: AcceptRemoteWorkspaceInvitation): Promise<import("./remote-invitations.js").RemoteWorkspaceInvitationAcceptance>;
34
46
  createApiKey(email: string, code: string, name: string, scopes?: string[], context?: RemoteWorkspaceContext): Promise<{
35
47
  [field: string]: unknown;
36
48
  key: string;
@@ -1,3 +1,4 @@
1
+ import { type ListRemoteWorkspaceInvitations, type IssueRemoteWorkspaceInvitation, type ResendRemoteWorkspaceInvitation, type RevokeRemoteWorkspaceInvitation, type AcceptRemoteWorkspaceInvitation } from "./remote-invitations.js";
1
2
  import { type LeaveRemoteWorkspace, type RemoteWorkspaceLeaveResult } from "./remote-workspace-leave.js";
2
3
  import { type RemoteWorkspaceContext, type RemoteAccountWorkspaces, type RemoteWorkspaceSession, type RemoteWorkspaceSelectionErrorCode } from "./remote-workspace-selection.js";
3
4
  import { type RemoteWorkspaceMembersOptions, type RemoteWorkspaceMembersPage } from "./remote-workspace.js";
@@ -148,6 +149,17 @@ export declare class RemoteSkillsClient {
148
149
  private requestWorkspaceMember;
149
150
  /** Leave only the explicitly confirmed current incarnation, once. No credential writes or retries. */
150
151
  leaveWorkspace(context: RemoteWorkspaceContext, input: LeaveRemoteWorkspace): Promise<RemoteWorkspaceLeaveResult>;
152
+ listWorkspaceInvitations(context: RemoteWorkspaceContext, options?: ListRemoteWorkspaceInvitations): Promise<import("./remote-invitations.js").RemoteWorkspaceInvitationsPage>;
153
+ getWorkspaceInvitation(context: RemoteWorkspaceContext, invitationId: string): Promise<{
154
+ invitation: import("./remote-invitations.js").RemoteWorkspaceInvitation;
155
+ }>;
156
+ issueWorkspaceInvitation(context: RemoteWorkspaceContext, input: IssueRemoteWorkspaceInvitation): Promise<import("./remote-invitations.js").RemoteWorkspaceInvitationResult>;
157
+ resendWorkspaceInvitation(context: RemoteWorkspaceContext, invitationId: string, input: ResendRemoteWorkspaceInvitation): Promise<import("./remote-invitations.js").RemoteWorkspaceInvitationResult>;
158
+ revokeWorkspaceInvitation(context: RemoteWorkspaceContext, invitationId: string, input: RevokeRemoteWorkspaceInvitation): Promise<import("./remote-invitations.js").RemoteWorkspaceInvitationResult>;
159
+ acceptWorkspaceInvitation(context: RemoteWorkspaceContext, invitationId: string, input: AcceptRemoteWorkspaceInvitation): Promise<import("./remote-invitations.js").RemoteWorkspaceInvitationAcceptance>;
160
+ /** One bounded operation, bound to the observed current incarnation. No retries,
161
+ * key/session persistence or post-acceptance selection of another workspace. */
162
+ private requestWorkspaceInvitation;
151
163
  listApiKeys(): Promise<Record<string, unknown>[]>;
152
164
  createApiKey(name: string, scopes?: string[]): Promise<{
153
165
  key: string;
@@ -0,0 +1,62 @@
1
+ export type RequestInvitationEmailChallenge = Readonly<{
2
+ invitationId: string;
3
+ token: string;
4
+ challengeId: string;
5
+ confirm: true;
6
+ }>;
7
+ export type AcceptInvitationEmailChallenge = RequestInvitationEmailChallenge & Readonly<{
8
+ code: string;
9
+ }>;
10
+ export type RemoteInvitationEmailChallenge = {
11
+ challengeId: string;
12
+ message: string;
13
+ expiresIn: 600;
14
+ };
15
+ export type RemoteInvitationEmailAcceptance = {
16
+ organizationId: string;
17
+ membershipId: string;
18
+ accepted: true;
19
+ changed: true;
20
+ signInRequired: true;
21
+ };
22
+ export declare class InvitationEmailInputError extends Error {
23
+ readonly code = "INVITATION_EMAIL_INPUT_INVALID";
24
+ constructor();
25
+ }
26
+ declare const refusals: {
27
+ readonly INVALID_REQUEST: readonly [400, "Invitation recovery parameters were refused."];
28
+ readonly ORIGIN_REQUIRED: readonly [403, "Invitation recovery requires the configured site origin."];
29
+ readonly INVITATION_PROOF_UNAVAILABLE: readonly [401, "Invitation proof is unavailable. Sign in or explicitly request another recovery code."];
30
+ readonly RATE_LIMITED: readonly [429, "Invitation verification is rate limited. Wait before another deliberate action."];
31
+ readonly INVITATION_BUSY: readonly [503, "Invitation is busy. Sign in to check membership before another deliberate action."];
32
+ readonly INVITATION_DELIVERY_UNAVAILABLE: readonly [503, "Invitation recovery is unavailable on this service."];
33
+ };
34
+ export type RemoteInvitationEmailErrorCode = keyof typeof refusals;
35
+ export declare class RemoteInvitationEmailError extends Error {
36
+ readonly code: RemoteInvitationEmailErrorCode;
37
+ readonly status: number;
38
+ constructor(code: RemoteInvitationEmailErrorCode);
39
+ }
40
+ export declare class RemoteInvitationEmailUnconfirmedError extends Error {
41
+ readonly action: "challenge" | "accept";
42
+ readonly code = "INVITATION_EMAIL_UNCONFIRMED";
43
+ constructor(action: "challenge" | "accept");
44
+ }
45
+ export declare function invitationEmailIds(invitationId: unknown, challengeId: unknown): {
46
+ invitationId: string;
47
+ challengeId: string;
48
+ };
49
+ export declare function invitationEmailInput<A extends "challenge" | "accept">(action: A, input: A extends "accept" ? AcceptInvitationEmailChallenge : RequestInvitationEmailChallenge): {
50
+ code?: string | undefined;
51
+ token: string;
52
+ confirm: true;
53
+ invitationId: string;
54
+ challengeId: string;
55
+ };
56
+ /** Explicit anonymous protocol: no auth resolver, headers, session creation or persistence. */
57
+ export declare function requestInvitationEmail<A extends "challenge" | "accept">(origin: string, action: A, input: A extends "accept" ? AcceptInvitationEmailChallenge : RequestInvitationEmailChallenge): Promise<A extends "accept" ? RemoteInvitationEmailAcceptance : RemoteInvitationEmailChallenge>;
58
+ export declare function invitationEmailCustomerError(error: unknown): {
59
+ code: string;
60
+ error: string;
61
+ };
62
+ export {};
@@ -0,0 +1,128 @@
1
+ import type { RemoteCustomerRole } from "./remote-profile.js";
2
+ export type RemoteWorkspaceInvitation = {
3
+ id: string;
4
+ organizationId: string;
5
+ email: string;
6
+ role: RemoteCustomerRole;
7
+ generation: number;
8
+ status: "pending" | "expired" | "accepted" | "revoked";
9
+ expiresAt: string;
10
+ createdAt: string;
11
+ delivery: {
12
+ state: "queued" | "sending" | "uncertain" | "provider_accepted" | "failed" | "cancelled";
13
+ attempts: number;
14
+ };
15
+ };
16
+ export type RemoteWorkspaceInvitationsPage = {
17
+ organizationId: string;
18
+ invitations: RemoteWorkspaceInvitation[];
19
+ nextCursor: string | null;
20
+ };
21
+ export type RemoteWorkspaceInvitationResult = {
22
+ invitation: RemoteWorkspaceInvitation;
23
+ changed: boolean;
24
+ };
25
+ export type RemoteWorkspaceInvitationAcceptance = {
26
+ organizationId: string;
27
+ membershipId: string;
28
+ accepted: true;
29
+ changed: boolean;
30
+ };
31
+ export type ListRemoteWorkspaceInvitations = Readonly<{
32
+ after?: string;
33
+ }>;
34
+ export type IssueRemoteWorkspaceInvitation = Readonly<{
35
+ email: string;
36
+ role: RemoteCustomerRole;
37
+ idempotencyKey: string;
38
+ confirm: true;
39
+ }>;
40
+ export type ResendRemoteWorkspaceInvitation = Readonly<{
41
+ expectedGeneration: number;
42
+ idempotencyKey: string;
43
+ confirm: true;
44
+ }>;
45
+ export type RevokeRemoteWorkspaceInvitation = Readonly<{
46
+ expectedGeneration: number;
47
+ confirm: true;
48
+ }>;
49
+ /** Secret input, never returned or persisted by the client. Acceptance does not select the new membership. */
50
+ export type AcceptRemoteWorkspaceInvitation = Readonly<{
51
+ token: string;
52
+ confirm: true;
53
+ }>;
54
+ export declare class WorkspaceInvitationInputError extends Error {
55
+ readonly code = "INVITATION_INPUT_INVALID";
56
+ constructor();
57
+ }
58
+ export declare const invitationFailures: {
59
+ readonly INVALID_REQUEST: readonly [400, "Invitation parameters were refused."];
60
+ readonly ACCOUNT_UNAVAILABLE: readonly [403, "Account is unavailable."];
61
+ readonly INTERACTIVE_SESSION_REQUIRED: readonly [403, "Fresh interactive sign-in is required."];
62
+ readonly WORKSPACE_ADMIN_REQUIRED: readonly [403, "A current workspace owner or admin is required."];
63
+ readonly INVITATION_FORBIDDEN: readonly [403, "Your current role cannot manage this invitation."];
64
+ readonly INVITATION_UNAVAILABLE: readonly [404, "Invitation is unavailable for this account."];
65
+ readonly INVITATION_CHANGED: readonly [409, "Invitation changed. Read its current generation before another action."];
66
+ readonly INVITATION_EXISTS: readonly [409, "A pending invitation already exists. Read current invitations."];
67
+ readonly ALREADY_MEMBER: readonly [409, "An active membership already exists. An invitation cannot change its role."];
68
+ readonly IDEMPOTENCY_CONFLICT: readonly [409, "This request key was used for different invitation parameters. Reconcile the original request."];
69
+ readonly INVITATION_LIMIT: readonly [429, "Invitation limit reached. Wait before issuing or resending."];
70
+ readonly INVITATION_BUSY: readonly [503, "Invitation is busy. Read its state before another action."];
71
+ readonly INVITATION_DELIVERY_UNAVAILABLE: readonly [503, "Invitation email delivery is unavailable."];
72
+ };
73
+ export type RemoteWorkspaceInvitationErrorCode = keyof typeof invitationFailures;
74
+ export declare class RemoteWorkspaceInvitationError extends Error {
75
+ readonly code: RemoteWorkspaceInvitationErrorCode;
76
+ readonly status: number;
77
+ constructor(code: RemoteWorkspaceInvitationErrorCode);
78
+ }
79
+ export declare class RemoteWorkspaceInvitationUnconfirmedError extends Error {
80
+ readonly code = "INVITATION_UNCONFIRMED";
81
+ constructor();
82
+ }
83
+ export declare class RemoteWorkspaceInvitationReadError extends Error {
84
+ readonly code = "INVITATION_READ_FAILED";
85
+ constructor();
86
+ }
87
+ export declare function invitationFailure(value: unknown, status: number): "INVALID_REQUEST" | "ACCOUNT_UNAVAILABLE" | "INTERACTIVE_SESSION_REQUIRED" | "WORKSPACE_ADMIN_REQUIRED" | "INVITATION_FORBIDDEN" | "INVITATION_UNAVAILABLE" | "INVITATION_CHANGED" | "INVITATION_EXISTS" | "ALREADY_MEMBER" | "IDEMPOTENCY_CONFLICT" | "INVITATION_LIMIT" | "INVITATION_BUSY" | "INVITATION_DELIVERY_UNAVAILABLE" | null;
88
+ export type InvitationAction = "list" | "get" | "issue" | "resend" | "revoke" | "accept";
89
+ export type InvitationInputs = {
90
+ list: ListRemoteWorkspaceInvitations;
91
+ get: Readonly<{
92
+ invitationId: string;
93
+ }>;
94
+ issue: IssueRemoteWorkspaceInvitation;
95
+ resend: ResendRemoteWorkspaceInvitation & Readonly<{
96
+ invitationId: string;
97
+ }>;
98
+ revoke: RevokeRemoteWorkspaceInvitation & Readonly<{
99
+ invitationId: string;
100
+ }>;
101
+ accept: AcceptRemoteWorkspaceInvitation & Readonly<{
102
+ invitationId: string;
103
+ }>;
104
+ };
105
+ export type InvitationResults = {
106
+ list: RemoteWorkspaceInvitationsPage;
107
+ get: {
108
+ invitation: RemoteWorkspaceInvitation;
109
+ };
110
+ issue: RemoteWorkspaceInvitationResult;
111
+ resend: RemoteWorkspaceInvitationResult;
112
+ revoke: RemoteWorkspaceInvitationResult;
113
+ accept: RemoteWorkspaceInvitationAcceptance;
114
+ };
115
+ export declare function invitationId(value: unknown): string;
116
+ /** Capture and validate all caller values before authentication or other awaits. */
117
+ export declare function invitationInput<A extends InvitationAction>(action: A, input: InvitationInputs[A]): InvitationInputs[A];
118
+ export declare function invitationRequest<A extends InvitationAction>(action: A, input: InvitationInputs[A]): {
119
+ path: string;
120
+ method: string;
121
+ body?: undefined;
122
+ } | {
123
+ path: string;
124
+ method: string;
125
+ body: string;
126
+ };
127
+ /** Project only validated contract fields; never surface arbitrary response metadata. */
128
+ export declare function parseInvitationResult<A extends InvitationAction>(action: A, value: unknown, input: InvitationInputs[A], organizationId: string): InvitationResults[A];
@@ -33,5 +33,58 @@ export declare function sha256Hex(bytes: Uint8Array): string;
33
33
  /** Collect the files a bundle would contain, in archive order. */
34
34
  export declare function collectSkillBundleEntries(dir: string): SkillBundleEntry[];
35
35
  export declare function packSkillBundle(dir: string, options?: PackSkillBundleOptions): PackedSkillBundle;
36
- /** Inverse of packSkillBundle. Used by the round-trip tests and by any future `pull`. */
36
+ /** Legacy synchronous reader for trusted inputs. Unbounded; use inspectSkillBundle for uploads. */
37
37
  export declare function unpackSkillBundle(bundle: Uint8Array): SkillBundleEntry[];
38
+ /** Hard ceilings. Callers may tighten these limits, never disable or raise them. */
39
+ export interface SkillBundleInspectionLimits {
40
+ compressedBytes: number;
41
+ decompressedBytes: number;
42
+ entries: number;
43
+ fileBytes: number;
44
+ pathBytes: number;
45
+ timeoutMs: number;
46
+ }
47
+ export declare const SKILL_BUNDLE_INSPECTION_LIMITS: Readonly<SkillBundleInspectionLimits>;
48
+ export interface InspectSkillBundleOptions {
49
+ limits?: Partial<SkillBundleInspectionLimits>;
50
+ signal?: AbortSignal;
51
+ }
52
+ export interface InspectedSkillBundle {
53
+ /** Each body has its own buffer. No path has been written or executed. */
54
+ entries: SkillBundleEntry[];
55
+ /** Hash of the complete owned compressed snapshot, not of extracted files. */
56
+ sha256: string;
57
+ compressedByteSize: number;
58
+ /** Includes headers, body padding, terminators and trailing zero padding. */
59
+ decompressedByteSize: number;
60
+ unpackedByteSize: number;
61
+ fileCount: number;
62
+ }
63
+ export type SkillBundleInspectionErrorCode = "BUNDLE_INVALID" | "BUNDLE_LIMIT" | "BUNDLE_ABORTED" | "BUNDLE_TIMEOUT";
64
+ export declare class SkillBundleInspectionError extends Error {
65
+ readonly code: SkillBundleInspectionErrorCode;
66
+ constructor(code: SkillBundleInspectionErrorCode, message: string);
67
+ }
68
+ /**
69
+ * Inspect a bounded gzipped ustar bundle without filesystem writes or execution.
70
+ * Resolves only after the entire gzip stream and tar structure validate. Returned
71
+ * entries are NOT permission to execute code or safely extract through existing
72
+ * filesystem symlinks; consumers still own storage, authorization and isolation.
73
+ *
74
+ * Only regular files, canonical relative slash paths (100 UTF-8 bytes maximum),
75
+ * no prefix/extension/link records, and modes without special bits are supported.
76
+ * Paths are unique under NFC + lowercase and cannot collide with a file ancestor.
77
+ * Noncanonical dot/empty/backslash segments are refused, not silently rewritten.
78
+ * Two zero tar blocks are required, followed only by complete zero padding blocks.
79
+ * Gzip members are decoded as one stream: an empty extra member is harmless, but
80
+ * a second nonempty archive after the tar terminator is rejected.
81
+ *
82
+ * The decoder has bounded stream buffers; decompressed bytes are counted before
83
+ * parsing or retaining each chunk, so expansion is stopped during decompression.
84
+ * Memory is bounded by the compressed snapshot, accepted file bodies, and stream
85
+ * buffers. The deadline covers copying, hashing, decoding and parsing, with both
86
+ * a timer and monotonic checks. Decoding yields to timers every 256 KiB so Bun's
87
+ * stream microtasks cannot starve a caller's scheduled abort. No partial entries
88
+ * escape on any failure.
89
+ */
90
+ export declare function inspectSkillBundle(bundle: Uint8Array, options?: InspectSkillBundleOptions): Promise<InspectedSkillBundle>;
@@ -0,0 +1,6 @@
1
+ /** Internal shared path policy for ordinary in-memory regular-file entries. */
2
+ export declare class SkillEntryPaths {
3
+ private readonly files;
4
+ private readonly directories;
5
+ add(path: string, maxBytes: number, invalid: (message: string) => never, limit: () => never): void;
6
+ }
@@ -1,4 +1,5 @@
1
1
  import type { PortableSkillManifest } from "./portable-skills-types.js";
2
+ import type { SkillBundleEntry } from "./skill-bundle.js";
2
3
  /**
3
4
  * Canonical content hashing for the hasna.skill.v1 portable bundle.
4
5
  *
@@ -49,6 +50,38 @@ export interface ContentHashVerification {
49
50
  /** The recomputed hash over the current bundle. */
50
51
  computedHash?: string;
51
52
  }
53
+ export interface ContentHashLimits {
54
+ entries: number;
55
+ rawBytes: number;
56
+ normalizedBytes: number;
57
+ fileBytes: number;
58
+ normalizedFileBytes: number;
59
+ pathBytes: number;
60
+ manifestBytes: number;
61
+ manifestDepth: number;
62
+ timeoutMs: number;
63
+ }
64
+ /** Hard ceilings for the entry API. Callers may tighten these, never disable them. */
65
+ export declare const CONTENT_HASH_LIMITS: Readonly<ContentHashLimits>;
66
+ export interface ContentHashOptions {
67
+ limits?: Partial<ContentHashLimits>;
68
+ signal?: AbortSignal;
69
+ }
70
+ export type ContentHashInputErrorCode = "CONTENT_HASH_INVALID" | "CONTENT_HASH_LIMIT" | "CONTENT_HASH_ABORTED" | "CONTENT_HASH_TIMEOUT";
71
+ export declare class ContentHashInputError extends Error {
72
+ readonly code: ContentHashInputErrorCode;
73
+ constructor(code: ContentHashInputErrorCode, message: string);
74
+ }
75
+ /**
76
+ * Hash bounded ordinary regular-file entries without filesystem access or extraction.
77
+ * Entries are revalidated and copied, even if supplied by inspectSkillBundle. This is
78
+ * content identity, not manifest validity, permission to execute, or a JS sandbox.
79
+ * Text uses the directory oracle's nonfatal UTF-8/LF normalization. Excluded paths
80
+ * still count toward input limits and collision checks. Inputs are never mutated.
81
+ */
82
+ export declare function computeContentHashFromEntries(entries: readonly SkillBundleEntry[], options?: ContentHashOptions): Promise<string>;
83
+ /** Verify only the declaration in the same owned skill.json, never a second manifest. */
84
+ export declare function verifyContentHashFromEntries(entries: readonly SkillBundleEntry[], options?: ContentHashOptions): Promise<ContentHashVerification>;
52
85
  /**
53
86
  * Verify a skill folder's declared content_hash against the recomputed
54
87
  * canonical hash of the current bundle. A missing declaration or a mismatch
@@ -34,4 +34,3 @@ export declare function assertSkillsMcpConfigured(env?: Record<string, string |
34
34
  * stdio server (BUG e3997558).
35
35
  */
36
36
  export declare function startMcpStdio(): Promise<void>;
37
- export { buildServer } from "./server.js";
@@ -0,0 +1,2 @@
1
+ /** Dedicated anonymous proof surface. Ordinary tools and credential resolution are not initialized. */
2
+ export declare function startInvitationRecoveryMcp(args: string[], env?: Record<string, string | undefined>): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerRemoteInvitationTools(server: McpServer): void;
@@ -42,3 +42,6 @@ export { WorkspaceContextInputError, WorkspaceIdentityMismatchError } from "../l
42
42
  export { RemoteWorkspaceSelectionError } from "../lib/remote-client.js";
43
43
  export type { LeaveRemoteWorkspace, RemoteWorkspaceLeaveResult, RemoteWorkspaceLeaveErrorCode } from "../lib/remote-workspace-leave.js";
44
44
  export { WorkspaceLeaveInputError, RemoteWorkspaceLeaveError, RemoteWorkspaceLeaveUnconfirmedError } from "../lib/remote-workspace-leave.js";
45
+ export type { RemoteWorkspaceInvitation, RemoteWorkspaceInvitationsPage, RemoteWorkspaceInvitationResult, RemoteWorkspaceInvitationAcceptance, ListRemoteWorkspaceInvitations, IssueRemoteWorkspaceInvitation, ResendRemoteWorkspaceInvitation, RevokeRemoteWorkspaceInvitation, AcceptRemoteWorkspaceInvitation, RemoteWorkspaceInvitationErrorCode } from "../lib/remote-invitations.js";
46
+ export { WorkspaceInvitationInputError, RemoteWorkspaceInvitationError, RemoteWorkspaceInvitationUnconfirmedError, RemoteWorkspaceInvitationReadError } from "../lib/remote-invitations.js";
47
+ export { InvitationEmailInputError, RemoteInvitationEmailError, RemoteInvitationEmailUnconfirmedError, type RequestInvitationEmailChallenge, type AcceptInvitationEmailChallenge, type RemoteInvitationEmailChallenge, type RemoteInvitationEmailAcceptance, type RemoteInvitationEmailErrorCode } from "../lib/remote-invitation-recovery.js";