@opengeni/vaults-protonpass 0.0.0-stage → 3.2.2

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 @@
1
+ {"version":3,"sources":["../src/provider.ts","../src/contract.ts","../src/naming.ts","../src/mapping.ts","../src/operations.ts","../src/schema.ts","../src/session.ts","../src/errors.ts","../src/runner.ts","../src/pool.ts"],"sourcesContent":["import { lstatSync, readFileSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n type ProviderCallBudget,\n type ProviderFieldValue,\n type ProviderItemMeta,\n type ProviderVault,\n type ProviderWriteField,\n type ProviderWriteItem,\n type SecretMaterial,\n VAULT_LIMITS,\n type VaultProvider,\n type VaultProviderCapabilities,\n type VaultProviderContext,\n VaultProviderError,\n type VaultProviderOperations,\n parseTotpInput,\n} from \"./contract\";\nimport { FILE_FIELD_PREFIX, type MappedField, type MappedItem, mapItem } from \"./mapping\";\nimport { nameKey, safeSecretName, totpUri } from \"./naming\";\nimport { restrictToOperations } from \"./operations\";\nimport {\n FullItemList,\n ITEM_HAS_FILES,\n type Item,\n ItemDetails,\n ItemSummaryList,\n SHARE_PERMISSION,\n ShareListOutput,\n type ShareRole,\n VaultListOutput,\n} from \"./schema\";\nimport { type ProtonCliOptions, type ProtonCommand, ProtonCliSession, parseJson } from \"./session\";\n\nexport const PROTON_PASS_VALUE_CACHE_MS = VAULT_LIMITS.providerValueCacheMs;\n/** Agent tokens cannot list with secrets, so each item is viewed; bound that fan-out. */\nexport const PROTON_PASS_MAX_ITEM_VIEWS_PER_LIST = 500;\n\n/** Operations pass-cli 2.4.2 supports without secrets on argv (see README). */\nexport const PROTON_PASS_OPERATIONS: VaultProviderOperations = {\n createItemTypes: [\"login\", \"note\", \"api_key\"],\n updateItem: false,\n removeField: false,\n archiveItem: true,\n archiveKind: \"trash\",\n deleteItem: false,\n restoreItem: false,\n readFiles: true,\n writeFiles: false,\n createTotp: true,\n updateTotp: false,\n createVault: false,\n restoreFieldHistory: false,\n};\n\n/** The adapter's capabilities; the same for every token (the PAT scope is enforced upstream). */\nexport function protonPassCapabilities(): VaultProviderCapabilities {\n return {\n write: true,\n createVault: false,\n totp: true,\n // Legacy flag means file writes; reads are declared in operations.readFiles.\n files: false,\n groupGrants: false,\n passkeys: false,\n operations: {\n ...PROTON_PASS_OPERATIONS,\n createItemTypes: [...PROTON_PASS_OPERATIONS.createItemTypes],\n },\n };\n}\n\nexport type ProtonPassVaultProviderOptions = ProtonCliOptions & {\n /** Operations verified at setup; the adapter narrows to them and never widens. */\n operations?: VaultProviderOperations;\n /** Personal access token `pst_…::…`, scoped by the customer to vaults or items. */\n token: string;\n valueCacheMs?: number;\n maxItemViewsPerList?: number;\n};\n\nexport type ProtonPassVaultProvider = VaultProvider & {\n readonly id: \"protonpass\";\n /** Logs the CLI session out and wipes its private state directory. */\n close(): Promise<void>;\n};\n\n/** Proton share and item ids are URL-safe base64; anything else cannot exist. */\nconst PROTON_ID = /^[A-Za-z0-9_=+/][A-Za-z0-9_=+/-]{0,255}$/;\nfunction assertIds(...ids: string[]) {\n for (const id of ids) {\n if (!PROTON_ID.test(id)) {\n throw new VaultProviderError(\"provider_not_found\", \"No such Proton Pass vault or item\");\n }\n }\n}\n\nconst TOKEN_SHAPE = /^[\\x21-\\x7e]{8,4096}$/;\n\ntype CachedDetails = { at: number; details: Promise<ItemDetails> };\n\nfunction writeAccessFor(role: ShareRole): \"read_only\" | \"read_write\" {\n if (typeof role === \"string\") return role === \"Viewer\" ? \"read_only\" : \"read_write\";\n return (role.Custom.permission & SHARE_PERMISSION.create) !== 0 ? \"read_write\" : \"read_only\";\n}\n\n/** Narrows a custom role's operations to its permission flags; built-in roles keep all. */\nfunction operationsFor(role: ShareRole): VaultProviderOperations | undefined {\n if (typeof role === \"string\") return undefined;\n const permission = role.Custom.permission;\n const canCreate = (permission & SHARE_PERMISSION.create) !== 0;\n const canTrash = (permission & SHARE_PERMISSION.trash) !== 0;\n return {\n ...PROTON_PASS_OPERATIONS,\n createItemTypes: canCreate ? [...PROTON_PASS_OPERATIONS.createItemTypes] : [],\n createTotp: canCreate,\n archiveItem: canTrash,\n archiveKind: canTrash ? \"trash\" : \"none\",\n };\n}\n\nfunction utf8Bytes(value: string): number {\n return Buffer.byteLength(value, \"utf8\");\n}\n\nfunction refuse(message: string): never {\n throw new VaultProviderError(\"provider_unavailable\", message);\n}\n\nfunction fieldValue(field: ProviderWriteField): string {\n if (field.remove) refuse(\"Proton Pass items cannot have fields removed from Opengeni\");\n const value = field.value ?? \"\";\n if (utf8Bytes(value) > VAULT_LIMITS.textValueMaxBytes) {\n refuse(`The value of \"${field.name}\" is larger than Opengeni stores`);\n }\n return value;\n}\n\nfunction totpValue(field: ProviderWriteField, label: string): string {\n try {\n return totpUri(parseTotpInput(fieldValue(field)), label);\n } catch (error) {\n if (error instanceof VaultProviderError) throw error;\n throw new VaultProviderError(\n \"provider_unavailable\",\n `\"${field.name}\" is not a TOTP seed or otpauth:// URI`,\n );\n }\n}\n\ntype CreatePlan = {\n kind: \"login\" | \"note\" | \"custom\";\n template: Record<string, unknown>;\n /** The same content as an Item, for metadata when the follow-up read fails. */\n synthetic: Item[\"content\"][\"content\"];\n note: string;\n extraSections: Array<{ section_name: string; section_fields: Item[\"content\"][\"extra_fields\"] }>;\n};\n\n/** Builds the `--from-template -` JSON for a create; values travel only on stdin. */\nexport function planCreate(item: ProviderWriteItem): CreatePlan {\n const title = item.name;\n if (item.type === \"login\") {\n let username: string | null = null;\n let email: string | null = null;\n let password: string | null = null;\n let totp: string | null = null;\n for (const field of item.fields) {\n const key = nameKey(field.name);\n if (field.kind === \"totp\") {\n if (totp !== null) refuse(\"Proton Pass logins hold one one-time password\");\n totp = totpValue(field, title);\n } else if (field.kind === \"text\" && key === \"username\" && username === null) {\n username = fieldValue(field);\n } else if (field.kind === \"text\" && key === \"email\" && email === null) {\n email = fieldValue(field);\n } else if (field.kind === \"concealed\" && key === \"password\" && password === null) {\n // Only a field named \"password\" becomes the login password; any other\n // name is refused before the create rather than silently renamed.\n password = fieldValue(field);\n } else {\n refuse(\n `Proton Pass logins created from Opengeni hold a username, email, password and one one-time password; \"${field.name}\" needs an API key (custom) item`,\n );\n }\n }\n const urls = item.websites.filter((url) => url.trim().length > 0);\n return {\n kind: \"login\",\n template: { title, username, email, password, totp_uri: totp, urls },\n synthetic: {\n Login: {\n username: username ?? \"\",\n email: email ?? \"\",\n password: password ?? \"\",\n totp_uri: totp ?? \"\",\n urls,\n },\n },\n note: \"\",\n extraSections: [],\n };\n }\n if (item.type === \"note\") {\n if (item.fields.length > 1) refuse(\"A Proton Pass note holds one note field\");\n const field = item.fields[0];\n if (field && field.kind !== \"text\" && field.kind !== \"concealed\") {\n refuse(\"A Proton Pass note holds text only\");\n }\n const note = field ? fieldValue(field) : \"\";\n return {\n kind: \"note\",\n template: { title, note },\n synthetic: { Note: null },\n note,\n extraSections: [],\n };\n }\n if (item.type === \"api_key\") {\n const fields = item.fields.map((field) => {\n if (field.kind === \"file\") refuse(\"Proton Pass files cannot be written from Opengeni\");\n const fieldType =\n field.kind === \"totp\" ? \"totp\" : field.kind === \"concealed\" ? \"hidden\" : \"text\";\n const value = field.kind === \"totp\" ? totpValue(field, title) : fieldValue(field);\n return { field_name: field.name, field_type: fieldType, value };\n });\n const sections = fields.length ? [{ section_name: \"Fields\", fields }] : [];\n return {\n kind: \"custom\",\n template: { title, note: null, sections },\n synthetic: {\n Custom: {\n sections: sections.map((section) => ({\n section_name: section.section_name,\n section_fields: section.fields.map((field) => ({\n name: field.field_name,\n content:\n field.field_type === \"totp\"\n ? { Totp: field.value }\n : field.field_type === \"hidden\"\n ? { Hidden: field.value }\n : { Text: field.value },\n })),\n })),\n },\n },\n note: \"\",\n extraSections: [],\n };\n }\n return refuse(\n item.type === \"passkey\"\n ? \"Passkeys live only in Opengeni vaults\"\n : \"Proton Pass file items cannot be created from Opengeni\",\n );\n}\n\nconst CREATE_CONTEXT = {\n login: /Error creating login item/,\n note: /Error creating note item/,\n custom: /Error creating custom item/,\n} as const;\n\nexport function createProtonPassVaultProvider(\n options: ProtonPassVaultProviderOptions,\n): ProtonPassVaultProvider {\n const token = options.token.trim();\n if (!TOKEN_SHAPE.test(token)) {\n throw new VaultProviderError(\n \"provider_auth_invalid\",\n \"A Proton Pass personal access token looks like pst_…::…\",\n );\n }\n const session = new ProtonCliSession(token, options);\n const now = options.now ?? Date.now;\n const valueCacheMs = options.valueCacheMs ?? PROTON_PASS_VALUE_CACHE_MS;\n // Per provider instance (one token, one session) and per attempt budget.\n // Core shares one budget across every provider in an attempt, so a\n // module-level cache keyed only by budget would let one connection read\n // another's values for the same share and item ids.\n const attemptCaches = new WeakMap<ProviderCallBudget, Map<string, CachedDetails>>();\n const maxViews = options.maxItemViewsPerList ?? PROTON_PASS_MAX_ITEM_VIEWS_PER_LIST;\n /** Last observed access per share; lets a known read-only vault refuse writes locally. */\n const shareAccess = new Map<string, \"read_only\" | \"read_write\" | \"unknown\">();\n\n function cli(\n ctx: VaultProviderContext,\n op: \"list\" | \"read\" | \"write\",\n command: Omit<ProtonCommand, \"authority\" | \"signal\">,\n ): Promise<string> {\n ctx.signal?.throwIfAborted();\n ctx.budget.take(op);\n return session.run({\n ...command,\n ...(ctx.authority ? { authority: ctx.authority } : {}),\n ...(ctx.signal ? { signal: ctx.signal } : {}),\n });\n }\n\n function parseOutput<T>(\n stdout: string,\n schema: { safeParse(value: unknown): { success: true; data: T } | { success: false } },\n code: \"provider_inventory_incomplete\" | \"provider_unavailable\",\n ): T {\n const parsed = schema.safeParse(parseJson(stdout));\n if (!parsed.success) {\n throw new VaultProviderError(\n code,\n \"pass-cli returned output this Opengeni release does not understand\",\n );\n }\n return parsed.data;\n }\n\n function viewItem(\n ctx: VaultProviderContext,\n shareId: string,\n itemId: string,\n subject: string,\n ): Promise<ItemDetails> {\n return cli(ctx, \"read\", {\n args: [\"item\", \"view\", `--share-id=${shareId}`, `--item-id=${itemId}`, \"--output\", \"json\"],\n subject,\n }).then((stdout) => parseOutput(stdout, ItemDetails, \"provider_unavailable\"));\n }\n\n /** Live item read, cached per attempt (keyed by its budget) with single-flight. */\n function cachedItem(ctx: VaultProviderContext, shareId: string, itemId: string) {\n let cache = attemptCaches.get(ctx.budget);\n if (!cache) {\n cache = new Map();\n attemptCaches.set(ctx.budget, cache);\n }\n const key = `${ctx.cacheEpoch ?? \"\"}|${shareId}/${itemId}`;\n const cached = cache.get(key);\n if (cached && !ctx.forceRefresh && now() - cached.at < valueCacheMs) return cached.details;\n const details = viewItem(ctx, shareId, itemId, \"read item\");\n const entry = { at: now(), details };\n cache.set(key, entry);\n details.catch(() => {\n if (cache.get(key) === entry) cache.delete(key);\n });\n return details;\n }\n\n function forgetItem(ctx: VaultProviderContext, shareId: string, itemId: string) {\n const cache = attemptCaches.get(ctx.budget);\n if (!cache) return;\n for (const key of cache.keys()) if (key.endsWith(`|${shareId}/${itemId}`)) cache.delete(key);\n }\n\n function reportFresh(ctx: VaultProviderContext) {\n const at = new Date(now()).toISOString();\n ctx.onFreshness?.({\n state: \"current\",\n lastCheckedAt: at,\n sourceSyncedAt: at,\n source: \"live\",\n errorCode: null,\n retryAt: null,\n });\n }\n\n async function downloadFile(\n ctx: VaultProviderContext,\n shareId: string,\n itemId: string,\n field: MappedField & { value: { type: \"file\" } },\n ): Promise<Uint8Array> {\n const attachment = field.value.attachment;\n assertIds(attachment.id);\n if (attachment.size > VAULT_LIMITS.fileValueMaxBytes) {\n refuse(`\"${field.name}\" is larger than Opengeni reads from Proton Pass`);\n }\n const dir = session.privateScratchDir();\n const target = join(dir, \"attachment\");\n try {\n await cli(ctx, \"read\", {\n args: [\n \"item\",\n \"attachment\",\n \"download\",\n `--share-id=${shareId}`,\n `--item-id=${itemId}`,\n `--attachment-id=${attachment.id}`,\n `--output=${target}`,\n ],\n subject: \"download attachment\",\n maxStdoutBytes: 64 * 1024,\n });\n let size: number;\n try {\n const stat = lstatSync(target);\n if (!stat.isFile()) throw new Error(\"not a file\");\n size = stat.size;\n } catch {\n return refuse(\"pass-cli did not produce the attachment\");\n }\n if (size > VAULT_LIMITS.fileValueMaxBytes) {\n refuse(`\"${field.name}\" is larger than Opengeni reads from Proton Pass`);\n }\n return new Uint8Array(readFileSync(target));\n } finally {\n rmSync(dir, { recursive: true, force: true });\n }\n }\n\n async function material(\n ctx: VaultProviderContext,\n shareId: string,\n itemId: string,\n mapped: MappedItem,\n externalFieldId: string,\n ): Promise<SecretMaterial> {\n const field = mapped.fields.find((candidate) => candidate.externalFieldId === externalFieldId);\n if (!field) {\n throw new VaultProviderError(\n \"provider_not_found\",\n `Proton Pass item \"${mapped.meta.name}\" has no field ${externalFieldId}`,\n );\n }\n const value = field.value;\n if (value.type === \"text\") return { type: \"text\", value: value.value };\n if (value.type === \"totp\") {\n try {\n return { type: \"totp\", params: parseTotpInput(value.uri) };\n } catch {\n return refuse(`The one-time password in \"${mapped.meta.name}\" is not a valid TOTP seed`);\n }\n }\n const bytes = await downloadFile(ctx, shareId, itemId, { ...field, value });\n return { type: \"bytes\", value: bytes };\n }\n\n const provider: ProtonPassVaultProvider = {\n id: \"protonpass\",\n\n capabilities: protonPassCapabilities,\n\n async validate(ctx) {\n ctx.signal?.throwIfAborted();\n const info = await session.ensureSession(ctx.signal);\n await provider.listVaults(ctx);\n return { accountName: info.tokenName };\n },\n\n async listVaults(ctx): Promise<ProviderVault[]> {\n let shares: ShareListOutput;\n try {\n shares = parseOutput(\n await cli(ctx, \"list\", {\n args: [\"share\", \"list\", \"--only-vaults=true\", \"--output\", \"json\"],\n subject: \"list vaults\",\n overflowCode: \"provider_inventory_incomplete\",\n }),\n ShareListOutput,\n \"provider_inventory_incomplete\",\n );\n } catch (error) {\n // Roles refine access; when shares are refused or unreadable, list vaults with unknown access.\n if (\n !(error instanceof VaultProviderError) ||\n ![\n \"provider_permission_denied\",\n \"provider_not_found\",\n \"provider_inventory_incomplete\",\n ].includes(error.code)\n ) {\n throw error;\n }\n const vaults = parseOutput(\n await cli(ctx, \"list\", {\n args: [\"vault\", \"list\", \"--output\", \"json\"],\n subject: \"list vaults\",\n overflowCode: \"provider_inventory_incomplete\",\n }),\n VaultListOutput,\n \"provider_inventory_incomplete\",\n );\n reportFresh(ctx);\n return vaults.vaults.map((vault) => {\n shareAccess.set(vault.share_id, \"unknown\");\n return {\n externalVaultId: vault.share_id,\n name: safeSecretName(vault.name, vault.share_id),\n contentVersion: null,\n itemCount: null,\n writeAccess: \"unknown\" as const,\n };\n });\n }\n reportFresh(ctx);\n return shares.shares\n .filter((share) => share.share_type === \"Vault\")\n .map((share) => {\n const writeAccess = writeAccessFor(share.share_role);\n shareAccess.set(share.id, writeAccess);\n const operations = operationsFor(share.share_role);\n return {\n externalVaultId: share.id,\n name: safeSecretName(share.name, share.id),\n contentVersion: null,\n itemCount: null,\n writeAccess,\n ...(operations ? { operations } : {}),\n };\n });\n },\n\n async listItems(ctx, externalVaultId): Promise<ProviderItemMeta[]> {\n assertIds(externalVaultId);\n await session.ensureSession(ctx.signal);\n const agent = session.sessionInfo?.agent ?? false;\n const base = [\"item\", \"list\", `--share-id=${externalVaultId}`, \"--filter-state\", \"active\"];\n const metas: ProviderItemMeta[] = [];\n if (!agent) {\n const list = parseOutput(\n await cli(ctx, \"list\", {\n args: [...base, \"--show-secrets\", \"--output\", \"json\"],\n subject: \"list items\",\n overflowCode: \"provider_inventory_incomplete\",\n }),\n FullItemList,\n \"provider_inventory_incomplete\",\n );\n // Only this share's items are viewed, so only they count against the view budget.\n const withFiles = list.items.filter(\n (item) => item.share_id === externalVaultId && item.flags.includes(ITEM_HAS_FILES),\n );\n if (withFiles.length > maxViews) incomplete();\n for (const item of list.items) {\n if (item.share_id !== externalVaultId) continue;\n if (item.flags.includes(ITEM_HAS_FILES)) {\n const details = await viewItem(ctx, externalVaultId, item.id, \"list items\");\n metas.push(mapItem(details.item, details.attachments).meta);\n } else {\n metas.push(mapItem(item).meta);\n }\n }\n } else {\n // Agent sessions refuse --show-secrets; each item is viewed (and audited) instead.\n const list = parseOutput(\n await cli(ctx, \"list\", {\n args: [...base, \"--output\", \"json\"],\n subject: \"list items\",\n overflowCode: \"provider_inventory_incomplete\",\n }),\n ItemSummaryList,\n \"provider_inventory_incomplete\",\n );\n const summaries = list.items.filter((item) => item.share_id === externalVaultId);\n if (summaries.length > maxViews) incomplete();\n for (const summary of summaries) {\n const details = await viewItem(ctx, externalVaultId, summary.id, \"list items\");\n metas.push(mapItem(details.item, details.attachments).meta);\n }\n }\n if (metas.length > VAULT_LIMITS.itemsPerVault) incomplete();\n for (const meta of metas) assertMirrorable(meta);\n reportFresh(ctx);\n return metas;\n },\n\n async readFields(ctx, externalVaultId, externalItemId, externalFieldIds) {\n assertIds(externalVaultId, externalItemId);\n const details = await cachedItem(ctx, externalVaultId, externalItemId);\n if (details.item.share_id !== externalVaultId || details.item.state !== \"Active\") {\n throw new VaultProviderError(\"provider_not_found\", \"No such Proton Pass vault or item\");\n }\n const mapped = mapItem(details.item, details.attachments);\n const values: ProviderFieldValue[] = [];\n for (const externalFieldId of externalFieldIds) {\n values.push({\n externalFieldId,\n material: await material(ctx, externalVaultId, externalItemId, mapped, externalFieldId),\n });\n }\n return values;\n },\n\n async writeItem(ctx, externalVaultId, item): Promise<ProviderItemMeta> {\n assertIds(externalVaultId);\n if (item.externalItemId !== undefined) {\n throw new VaultProviderError(\n \"provider_unavailable\",\n \"Proton Pass items cannot be updated from Opengeni: pass-cli 2.4.2 takes new values only as command-line arguments and cannot edit one-time passwords\",\n );\n }\n if (shareAccess.get(externalVaultId) === \"read_only\") {\n throw new VaultProviderError(\n \"provider_permission_denied\",\n \"The Proton Pass token can only read this vault\",\n );\n }\n const plan = planCreate(item);\n const stdout = await cli(ctx, \"write\", {\n args: [\n \"item\",\n \"create\",\n plan.kind,\n `--share-id=${externalVaultId}`,\n \"--from-template\",\n \"-\",\n ],\n stdin: JSON.stringify(plan.template),\n subject: `create ${plan.kind} item`,\n mutationContext: CREATE_CONTEXT[plan.kind],\n maxStdoutBytes: 64 * 1024,\n });\n const lines = stdout\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean);\n const itemId = lines.at(-1);\n if (!itemId || !PROTON_ID.test(itemId)) {\n throw new VaultProviderError(\n \"provider_outcome_unknown\",\n \"Proton Pass did not confirm the new item; check the vault before retrying\",\n );\n }\n try {\n const details = await viewItem(ctx, externalVaultId, itemId, \"read created item\");\n return mapItem(details.item, details.attachments).meta;\n } catch {\n // The item exists; when the follow-up read fails, describe it from what was sent.\n const synthetic = mapItem({\n id: itemId,\n share_id: externalVaultId,\n content: {\n title: item.name,\n note: plan.note,\n content: plan.synthetic,\n extra_fields: [],\n },\n state: \"Active\",\n flags: [],\n create_time: \"1970-01-01T00:00:00\",\n modify_time: \"1970-01-01T00:00:00\",\n }).meta;\n return { ...synthetic, version: null, updatedAt: null };\n }\n },\n\n async archiveItem(ctx, externalVaultId, externalItemId) {\n assertIds(externalVaultId, externalItemId);\n if (shareAccess.get(externalVaultId) === \"read_only\") {\n throw new VaultProviderError(\n \"provider_permission_denied\",\n \"The Proton Pass token can only read this vault\",\n );\n }\n // Trash is recoverable in Proton Pass; `item delete` (permanent) is never used.\n await cli(ctx, \"write\", {\n args: [\"item\", \"trash\", `--share-id=${externalVaultId}`, `--item-id=${externalItemId}`],\n subject: \"trash item\",\n mutationContext: /Error trashing item/,\n maxStdoutBytes: 64 * 1024,\n });\n forgetItem(ctx, externalVaultId, externalItemId);\n },\n\n close: () => session.close(),\n };\n return restrictToOperations(provider, options.operations, FILE_FIELD_PREFIX);\n}\n\nfunction incomplete(): never {\n throw new VaultProviderError(\n \"provider_inventory_incomplete\",\n \"The Proton Pass vault has more items than Opengeni mirrors at once\",\n );\n}\n\n/**\n * Opengeni mirrors at most `fieldsPerItem` fields and `websitesPerItem`\n * websites of up to `websiteMaxChars` each. A larger item would be cut down\n * and then look complete, so the listing is reported incomplete instead.\n */\nfunction assertMirrorable(meta: ProviderItemMeta): void {\n if (\n meta.fields.length > VAULT_LIMITS.fieldsPerItem ||\n meta.websites.length > VAULT_LIMITS.websitesPerItem ||\n meta.websites.some((website) => website.length > VAULT_LIMITS.websiteMaxChars)\n ) {\n throw new VaultProviderError(\n \"provider_inventory_incomplete\",\n `A Proton Pass item has more than ${VAULT_LIMITS.fieldsPerItem} fields or ${VAULT_LIMITS.websitesPerItem} websites (or a website over ${VAULT_LIMITS.websiteMaxChars} characters), more than Opengeni mirrors`,\n );\n }\n}\n","/**\n * The shared vault contracts this adapter implements, re-exported for the\n * package's modules so every file names one source.\n */\nexport {\n VaultProviderError,\n type ProviderCallBudget,\n type ProviderCallOperation,\n type ProviderFieldMeta,\n type ProviderFieldValue,\n type ProviderItemMeta,\n type ProviderVault,\n type ProviderWriteField,\n type ProviderWriteItem,\n type VaultProvider,\n type VaultProviderAuthority,\n type VaultProviderCapabilities,\n type VaultProviderContext,\n type VaultProviderErrorCode,\n} from \"@opengeni/vaults\";\nexport {\n VAULT_LIMITS,\n parseTotpInput,\n type SecretMaterial,\n type TotpParams,\n type VaultFieldKind,\n type VaultItemType,\n type VaultProviderOperations,\n} from \"@opengeni/contracts\";\n","import { type TotpParams, VAULT_LIMITS } from \"./contract\";\n\n// Mirrors contracts isValidSecretName (Q-10): no / { } # \\ or control chars,\n// trimmed, 1..120 chars, not \"id:…\"; field names additionally may not be \"otp\".\nconst FORBIDDEN_NAME_CHARS = /[/{}#\\\\\\u0000-\\u001f\\u007f-\\u009f]/g;\n\nexport function nameKey(name: string): string {\n return name.normalize(\"NFC\").trim().toLowerCase();\n}\n\nexport function safeSecretName(raw: string, fallback: string): string {\n const max = VAULT_LIMITS.nameMaxChars;\n let name = raw.replace(FORBIDDEN_NAME_CHARS, \"-\").trim().slice(0, max).trim();\n if (!name) name = fallback.replace(FORBIDDEN_NAME_CHARS, \"-\").trim().slice(0, max) || \"item\";\n if (/^id:/i.test(name)) name = `id-${name.slice(3)}`;\n return name;\n}\n\nexport function safeFieldName(raw: string, fallback: string): string {\n const name = safeSecretName(raw, fallback);\n return nameKey(name) === \"otp\" ? \"otp-code\" : name;\n}\n\n/** Appends \" (2)\", \" (3)\" … so names are unique case-insensitively. */\nexport function uniqueName(name: string, taken: Set<string>): string {\n let candidate = name;\n for (let n = 2; taken.has(nameKey(candidate)); n += 1) {\n const suffix = ` (${n})`;\n candidate = `${name.slice(0, VAULT_LIMITS.nameMaxChars - suffix.length)}${suffix}`;\n }\n taken.add(nameKey(candidate));\n return candidate;\n}\n\n/** A canonical otpauth URI for a parsed seed, for stores that require URIs. */\nexport function totpUri(params: TotpParams, label: string): string {\n const query = new URLSearchParams({\n secret: params.secretBase32,\n algorithm: params.algorithm,\n digits: String(params.digits),\n period: String(params.periodSeconds),\n });\n return `otpauth://totp/${encodeURIComponent(label || \"Opengeni\")}?${query.toString()}`;\n}\n","import {\n type ProviderFieldMeta,\n type ProviderItemMeta,\n type VaultFieldKind,\n type VaultItemType,\n} from \"./contract\";\nimport { safeFieldName, safeSecretName, uniqueName } from \"./naming\";\nimport type { Attachment, ExtraField, Item, ItemContentVariant, Section } from \"./schema\";\n\n/**\n * External field ids. They are positional names, not upstream ids: Proton\n * items have no per-field identifiers, so ids are derived from the field's\n * place in the item (`login.password`, `x:<extra field name>`,\n * `s:<section>/<field>`, `@file:<attachment id>`), with `#n` for repeats.\n */\nexport const NOTE_FIELD_ID = \"@note\";\nexport const FILE_FIELD_PREFIX = \"@file:\";\nexport const LOGIN_FIELD_IDS = {\n username: \"login.username\",\n email: \"login.email\",\n password: \"login.password\",\n totp: \"login.totp\",\n} as const;\nexport const TOTP_FIELD_NAME = \"one-time password\";\n\nexport type MappedValue =\n | { type: \"text\"; value: string }\n | { type: \"totp\"; uri: string }\n | { type: \"file\"; attachment: Attachment };\n\nexport interface MappedField extends ProviderFieldMeta {\n value: MappedValue;\n}\n\nexport interface MappedItem {\n meta: ProviderItemMeta;\n fields: MappedField[];\n}\n\nconst IDENTITY_CONCEALED = new Set([\"social_security_number\", \"passport_number\", \"license_number\"]);\n\nclass FieldCollector {\n readonly fields: MappedField[] = [];\n private readonly names = new Set<string>();\n private readonly ids = new Map<string, number>();\n\n add(baseId: string, rawName: string, kind: VaultFieldKind, value: MappedValue) {\n const seen = (this.ids.get(baseId) ?? 0) + 1;\n this.ids.set(baseId, seen);\n const externalFieldId = seen === 1 ? baseId : `${baseId}#${seen}`;\n const name = uniqueName(safeFieldName(rawName, \"field\"), this.names);\n this.fields.push({ externalFieldId, name, kind, value });\n }\n\n extra(prefix: string, field: ExtraField) {\n const content = field.content;\n const id = `${prefix}${field.name}`;\n if (\"Text\" in content) this.add(id, field.name, \"text\", { type: \"text\", value: content.Text });\n else if (\"Hidden\" in content) {\n this.add(id, field.name, \"concealed\", { type: \"text\", value: content.Hidden });\n } else if (\"Totp\" in content) {\n // An empty TOTP field holds no seed; it reads as empty text.\n if (content.Totp) this.add(id, field.name, \"totp\", { type: \"totp\", uri: content.Totp });\n else this.add(id, field.name, \"text\", { type: \"text\", value: \"\" });\n } else {\n this.add(id, field.name, \"text\", { type: \"text\", value: timestampText(content.Timestamp) });\n }\n }\n\n sections(sections: readonly Section[]) {\n for (const section of sections) {\n for (const field of section.section_fields) this.extra(`s:${section.section_name}/`, field);\n }\n }\n}\n\nfunction timestampText(seconds: number): string {\n const date = new Date(seconds * 1000);\n return Number.isNaN(date.getTime()) ? String(seconds) : date.toISOString();\n}\n\nfunction variantName(content: ItemContentVariant): string {\n if (typeof content === \"string\") return content;\n return Object.keys(content)[0] ?? \"Note\";\n}\n\nexport function itemTypeForVariant(variant: string): VaultItemType {\n switch (variant) {\n case \"Login\":\n return \"login\";\n case \"Note\":\n return \"note\";\n case \"Custom\":\n case \"SshKey\":\n return \"api_key\";\n default:\n // Alias, CreditCard, Identity, Wifi: generic fields, shown as notes.\n return \"note\";\n }\n}\n\n/** Proton summary `item_type` (snake case) to an Opengeni item type. */\nexport function itemTypeForSummary(itemType: string): VaultItemType {\n switch (itemType) {\n case \"login\":\n return \"login\";\n case \"custom\":\n case \"ssh_key\":\n return \"api_key\";\n default:\n return \"note\";\n }\n}\n\n/** `YYYY-MM-DDTHH:MM:SS` (UTC under TZ=UTC) to an ISO instant. */\nexport function civilToIso(civil: string): string | null {\n const date = new Date(`${civil}Z`);\n return Number.isNaN(date.getTime()) ? null : date.toISOString();\n}\n\nfunction concealedText(collector: FieldCollector, id: string, name: string, value: string) {\n collector.add(id, name, \"concealed\", { type: \"text\", value });\n}\n\nfunction plainText(collector: FieldCollector, id: string, name: string, value: string) {\n collector.add(id, name, \"text\", { type: \"text\", value });\n}\n\nfunction identityFields(collector: FieldCollector, identity: Record<string, unknown>) {\n for (const [key, value] of Object.entries(identity)) {\n if (typeof value === \"string\") {\n if (!value) continue;\n if (IDENTITY_CONCEALED.has(key)) concealedText(collector, `identity.${key}`, key, value);\n else plainText(collector, `identity.${key}`, key, value);\n continue;\n }\n if (!Array.isArray(value)) continue;\n for (const entry of value) {\n if (!entry || typeof entry !== \"object\") continue;\n const record = entry as Record<string, unknown>;\n if (typeof record.section_name === \"string\" && Array.isArray(record.section_fields)) {\n collector.sections([\n { section_name: record.section_name, section_fields: extraFields(record.section_fields) },\n ]);\n } else {\n for (const field of extraFields([record])) collector.extra(`s:${key}/`, field);\n }\n }\n }\n}\n\nfunction extraFields(values: readonly unknown[]): ExtraField[] {\n const out: ExtraField[] = [];\n for (const value of values) {\n if (!value || typeof value !== \"object\") continue;\n const record = value as { name?: unknown; content?: unknown };\n if (typeof record.name !== \"string\" || !record.content || typeof record.content !== \"object\") {\n continue;\n }\n const content = record.content as Record<string, unknown>;\n if (typeof content.Text === \"string\")\n out.push({ name: record.name, content: { Text: content.Text } });\n else if (typeof content.Hidden === \"string\") {\n out.push({ name: record.name, content: { Hidden: content.Hidden } });\n } else if (typeof content.Totp === \"string\") {\n out.push({ name: record.name, content: { Totp: content.Totp } });\n } else if (typeof content.Timestamp === \"number\") {\n out.push({ name: record.name, content: { Timestamp: content.Timestamp } });\n }\n }\n return out;\n}\n\n/** Maps an item (and, from `item view`, its attachments) to fields and metadata. */\nexport function mapItem(item: Item, attachments: readonly Attachment[] = []): MappedItem {\n const collector = new FieldCollector();\n const content = item.content.content;\n const variant = variantName(content);\n const websites: string[] = [];\n\n if (typeof content === \"object\") {\n if (\"Login\" in content) {\n const login = content.Login;\n plainText(collector, LOGIN_FIELD_IDS.username, \"username\", login.username);\n if (login.email) plainText(collector, LOGIN_FIELD_IDS.email, \"email\", login.email);\n concealedText(collector, LOGIN_FIELD_IDS.password, \"password\", login.password);\n if (login.totp_uri) {\n collector.add(LOGIN_FIELD_IDS.totp, TOTP_FIELD_NAME, \"totp\", {\n type: \"totp\",\n uri: login.totp_uri,\n });\n }\n websites.push(...login.urls.filter((url) => url.trim().length > 0));\n } else if (\"SshKey\" in content) {\n concealedText(collector, \"ssh.private_key\", \"private key\", content.SshKey.private_key);\n plainText(collector, \"ssh.public_key\", \"public key\", content.SshKey.public_key);\n collector.sections(content.SshKey.sections);\n } else if (\"Wifi\" in content) {\n plainText(collector, \"wifi.ssid\", \"ssid\", content.Wifi.ssid);\n concealedText(collector, \"wifi.password\", \"password\", content.Wifi.password);\n collector.sections(content.Wifi.sections);\n } else if (\"CreditCard\" in content) {\n const card = content.CreditCard;\n plainText(collector, \"card.cardholder_name\", \"cardholder name\", card.cardholder_name);\n concealedText(collector, \"card.number\", \"number\", card.number);\n concealedText(\n collector,\n \"card.verification_number\",\n \"verification number\",\n card.verification_number,\n );\n plainText(collector, \"card.expiration_date\", \"expiration date\", card.expiration_date);\n if (card.pin) concealedText(collector, \"card.pin\", \"PIN\", card.pin);\n } else if (\"Identity\" in content) {\n identityFields(collector, content.Identity);\n } else if (\"Custom\" in content) {\n collector.sections(content.Custom.sections);\n }\n }\n\n const note = item.content.note;\n if (variant === \"Note\" || note) {\n collector.add(NOTE_FIELD_ID, \"note\", \"concealed\", { type: \"text\", value: note });\n }\n for (const field of item.content.extra_fields) collector.extra(\"x:\", field);\n for (const attachment of attachments) {\n collector.add(`${FILE_FIELD_PREFIX}${attachment.id}`, attachment.content.name, \"file\", {\n type: \"file\",\n attachment,\n });\n }\n\n const meta: ProviderItemMeta = {\n externalItemId: item.id,\n name: safeSecretName(item.content.title, item.id),\n type: itemTypeForVariant(variant),\n websites,\n fields: collector.fields.map(({ externalFieldId, name, kind }) => ({\n externalFieldId,\n name,\n kind,\n })),\n version: item.modify_time,\n updatedAt: civilToIso(item.modify_time),\n };\n return { meta, fields: collector.fields };\n}\n","import { providerOperations } from \"@opengeni/vaults\";\nimport {\n VaultProviderError,\n type ProviderWriteItem,\n type VaultProvider,\n type VaultProviderOperations,\n} from \"./contract\";\n\nfunction refused(what: string): never {\n throw new VaultProviderError(\n \"provider_permission_denied\",\n `${what} is not enabled for this vault connection`,\n );\n}\n\nfunction checkWrite(operations: VaultProviderOperations, item: ProviderWriteItem) {\n const totp = item.fields.some((field) => field.kind === \"totp\" && !field.remove);\n if (item.externalItemId !== undefined) {\n if (!operations.updateItem) refused(\"Updating items\");\n if (totp && !operations.updateTotp) refused(\"Changing one-time password seeds\");\n if (item.fields.some((field) => field.remove) && !operations.removeField)\n refused(\"Removing fields\");\n return;\n }\n if (!operations.createItemTypes.includes(item.type)) refused(`Creating ${item.type} items`);\n if (totp && !operations.createTotp) refused(\"Adding one-time password seeds\");\n}\n\n/**\n * Narrows an adapter to the operations verified when its connection was set\n * up: what it reports and what it will do. It never widens the adapter's own\n * operations, and refused calls make no provider request.\n */\nexport function restrictToOperations<P extends VaultProvider>(\n provider: P,\n verified: VaultProviderOperations | undefined,\n fileFieldPrefix: string,\n): P {\n if (!verified) return provider;\n const effective = () =>\n providerOperations(provider.capabilities(), { operations: verified, writeAccess: \"unknown\" });\n return {\n ...provider,\n capabilities() {\n const base = provider.capabilities();\n const operations = effective();\n const writes =\n operations.createItemTypes.length > 0 || operations.updateItem || operations.archiveItem;\n return { ...base, write: base.write && writes, operations };\n },\n async readFields(ctx, vaultId, itemId, fieldIds) {\n if (!effective().readFiles && fieldIds.some((id) => id.startsWith(fileFieldPrefix)))\n refused(\"Reading files\");\n return provider.readFields(ctx, vaultId, itemId, fieldIds);\n },\n async writeItem(ctx, vaultId, item) {\n checkWrite(effective(), item);\n return provider.writeItem(ctx, vaultId, item);\n },\n async archiveItem(ctx, vaultId, itemId) {\n if (!effective().archiveItem) refused(\"Archiving items\");\n return provider.archiveItem(ctx, vaultId, itemId);\n },\n };\n}\n","import { z } from \"zod\";\n\n/**\n * JSON shapes printed by pass-cli 2.4.2 with `--output json` (serde of the\n * pass crate and proton-pass-common 2.1.1 types). Unknown keys are dropped;\n * only what the adapter maps is validated, so additive upstream fields do not\n * break parsing while a changed shape fails closed.\n */\n\nconst Id = z.string().min(1).max(512);\n/** jiff civil date-time; pass-cli runs with TZ=UTC so it is UTC wall time. */\nconst CivilDateTime = z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,9})?)?$/);\n\nconst ShareRole = z.union([\n z.enum([\"Owner\", \"Manager\", \"Editor\", \"Viewer\"]),\n z.object({\n Custom: z.object({ name: z.string().optional(), permission: z.number().int().min(0) }),\n }),\n]);\nexport type ShareRole = z.infer<typeof ShareRole>;\n\n/** `share list --only-vaults=true --output json` */\nexport const ShareListOutput = z.object({\n shares: z.array(\n z.object({\n id: Id,\n name: z.string(),\n share_type: z.string(),\n share_role: ShareRole,\n }),\n ),\n});\nexport type ShareListOutput = z.infer<typeof ShareListOutput>;\n\n/** `vault list --output json` (fallback when share roles are unavailable). */\nexport const VaultListOutput = z.object({\n vaults: z.array(z.object({ name: z.string(), vault_id: Id, share_id: Id })),\n});\n\nexport const ExtraFieldContent = z.union([\n z.object({ Text: z.string() }),\n z.object({ Hidden: z.string() }),\n z.object({ Totp: z.string() }),\n z.object({ Timestamp: z.number().int() }),\n]);\nexport const ExtraField = z.object({ name: z.string(), content: ExtraFieldContent });\nexport type ExtraField = z.infer<typeof ExtraField>;\n\nconst Section = z.object({ section_name: z.string(), section_fields: z.array(ExtraField) });\nexport type Section = z.infer<typeof Section>;\n\nconst OptionalString = z\n .string()\n .nullish()\n .transform((value) => value ?? \"\");\n\nconst LoginContent = z.object({\n email: OptionalString,\n username: OptionalString,\n password: OptionalString,\n urls: z.array(z.string()).default([]),\n totp_uri: OptionalString,\n});\nconst SshKeyContent = z.object({\n private_key: OptionalString,\n public_key: OptionalString,\n sections: z.array(Section).default([]),\n});\nconst WifiContent = z.object({\n ssid: OptionalString,\n password: OptionalString,\n sections: z.array(Section).default([]),\n});\nconst CreditCardContent = z.object({\n cardholder_name: OptionalString,\n number: OptionalString,\n verification_number: OptionalString,\n expiration_date: OptionalString,\n pin: OptionalString,\n});\n/** Identity carries many scalar strings plus extra field groups; kept loose. */\nconst IdentityContent = z.record(z.string(), z.unknown());\nconst CustomContent = z.object({ sections: z.array(Section).default([]) });\n\nexport const ItemContentVariant = z.union([\n z.object({ Note: z.null() }).strict(),\n z.object({ Alias: z.null() }).strict(),\n z.object({ Login: LoginContent }),\n z.object({ SshKey: SshKeyContent }),\n z.object({ Wifi: WifiContent }),\n z.object({ CreditCard: CreditCardContent }),\n z.object({ Identity: IdentityContent }),\n z.object({ Custom: CustomContent }),\n z.literal(\"Note\"),\n z.literal(\"Alias\"),\n]);\nexport type ItemContentVariant = z.infer<typeof ItemContentVariant>;\n\nexport const Item = z.object({\n id: Id,\n share_id: Id,\n vault_id: z.string().optional(),\n content: z.object({\n title: z.string(),\n note: OptionalString,\n content: ItemContentVariant,\n extra_fields: z.array(ExtraField).default([]),\n }),\n state: z.string(),\n flags: z.array(z.string()).default([]),\n create_time: CivilDateTime,\n modify_time: CivilDateTime,\n});\nexport type Item = z.infer<typeof Item>;\n\nexport const Attachment = z.object({\n id: Id,\n size: z.number().int().min(0),\n content: z.object({ name: z.string(), mime_type: z.string().optional() }),\n});\nexport type Attachment = z.infer<typeof Attachment>;\n\n/** `item view --output json`: `ItemDetails`. */\nexport const ItemDetails = z.object({\n item: Item,\n attachments: z.array(Attachment).default([]),\n});\nexport type ItemDetails = z.infer<typeof ItemDetails>;\n\n/** `item list --show-secrets --output json` (non-agent sessions only). */\nexport const FullItemList = z.object({ items: z.array(Item) });\n\n/** `item list --output json`: secret-free summaries (the only form agent sessions get). */\nexport const ItemSummary = z.object({\n id: Id,\n share_id: Id,\n state: z.string(),\n flags: z.array(z.string()).default([]),\n create_time: CivilDateTime,\n modify_time: CivilDateTime,\n title: z.string(),\n item_type: z.string(),\n});\nexport type ItemSummary = z.infer<typeof ItemSummary>;\nexport const ItemSummaryList = z.object({ items: z.array(ItemSummary) });\n\n/** `info --output json` for a personal-access-token or agent session. */\nexport const InfoOutput = z.object({\n personal_access_token_name: z.string().optional(),\n username: z.string().optional(),\n session_has_lock: z.boolean().optional(),\n});\n\nexport const ITEM_HAS_FILES = \"ItemHasFiles\";\n\n/** Proton share permission flags (proton-pass-common ShareRole::Custom). */\nexport const SHARE_PERMISSION = {\n admin: 1,\n read: 2,\n create: 4,\n update: 8,\n trash: 16,\n delete: 32,\n} as const;\n","import { createHash, randomBytes } from \"node:crypto\";\nimport {\n accessSync,\n chmodSync,\n constants as fsConstants,\n createReadStream,\n lstatSync,\n mkdirSync,\n mkdtempSync,\n realpathSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { delimiter, isAbsolute, join, resolve } from \"node:path\";\nimport { VaultProviderError, type VaultProviderAuthority } from \"./contract\";\nimport {\n NOT_AUTHENTICATED,\n SESSION_INVALIDATED,\n isDefiniteMutationFailure,\n loginFailure,\n mapProtonFailure,\n outcomeUnknown,\n} from \"./errors\";\nimport { type ProcessResult, type ProcessRunner, runProcess } from \"./runner\";\nimport { InfoOutput } from \"./schema\";\n\n/** The only pass-cli release whose argv, JSON output and errors this adapter was built against. */\nexport const PROTON_PASS_CLI_VERSION = \"2.4.2\";\n/** A PAT login session is treated as stale before Proton's 2 h session lifetime. */\nexport const PROTON_PASS_SESSION_MAX_AGE_MS = 105 * 60_000;\nexport const PROTON_PASS_IDLE_CLOSE_MS = 15 * 60_000;\nexport const PROTON_PASS_COMMAND_TIMEOUT_MS = 60_000;\nexport const PROTON_PASS_MAX_STDOUT_BYTES = 32 * 1024 * 1024;\n/** pass/src/monitor MAX_REASON_LENGTH. */\nexport const PROTON_PASS_MAX_REASON_CHARS = 300;\n/** pass-cli processes allowed at once across every Proton connection in this process. */\nexport const PROTON_PASS_MAX_PROCESSES = 4;\n\nconst MAX_STDERR_BYTES = 16 * 1024;\nconst SMALL_STDOUT_BYTES = 256 * 1024;\nconst PASSTHROUGH_ENV = [\n \"HTTPS_PROXY\",\n \"HTTP_PROXY\",\n \"NO_PROXY\",\n \"https_proxy\",\n \"http_proxy\",\n \"no_proxy\",\n \"SSL_CERT_FILE\",\n \"SSL_CERT_DIR\",\n] as const;\n\nexport interface ProtonCliOptions {\n /** Absolute path to an operator-installed pass-cli; defaults to `pass-cli` on PATH. */\n binaryPath?: string;\n /** Exact `pass-cli --version` semver to accept (default 2.4.2). */\n expectedVersion?: string;\n /** Optional SHA-256 (hex) the binary must match. */\n expectedSha256?: string;\n /** Parent of per-connection state directories (default `<tmpdir>/opengeni-protonpass`). */\n stateRoot?: string;\n commandTimeoutMs?: number;\n maxStdoutBytes?: number;\n sessionMaxAgeMs?: number;\n idleCloseMs?: number;\n now?: () => number;\n /** Process runner (tests). Defaults to a no-shell, bounded `spawn`. */\n runner?: ProcessRunner;\n /** Process environment used only to resolve PATH and proxy settings (tests). */\n hostEnv?: Readonly<Record<string, string | undefined>>;\n}\n\nexport interface ProtonCommand {\n args: readonly string[];\n stdin?: string;\n /** Short action name for errors and the agent reason, e.g. \"list items\". */\n subject: string;\n authority?: VaultProviderAuthority;\n signal?: AbortSignal;\n /** Set for writes: failures are definite only with this context and a server verdict. */\n mutationContext?: RegExp;\n /** Error code when stdout exceeds its bound (list: inventory incomplete). */\n overflowCode?: \"provider_inventory_incomplete\" | \"provider_unavailable\";\n maxStdoutBytes?: number;\n}\n\nexport interface ProtonSessionInfo {\n tokenName: string | null;\n agent: boolean;\n}\n\n// --- process-wide bookkeeping ------------------------------------------------\n\nexport interface SlotSemaphore {\n /** Resolves with a release function once a slot is held; rejects if `signal` aborts first. */\n acquire(signal?: AbortSignal): Promise<() => void>;\n /** Slots held, including ones handed to a waiter that has not resumed yet. */\n active(): number;\n waiting(): number;\n}\n\n/**\n * A FIFO counting semaphore. A released slot is handed straight to the next\n * waiter (the count never drops in between), so a caller arriving while the\n * waiter resumes cannot take the same slot and exceed `limit`.\n */\nexport function createSlotSemaphore(limit: number): SlotSemaphore {\n let active = 0;\n const waiters: Array<() => void> = [];\n function releaser(): () => void {\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const next = waiters.shift();\n if (next) next();\n else active -= 1;\n };\n }\n return {\n async acquire(signal) {\n if (active < limit) {\n active += 1;\n return releaser();\n }\n await new Promise<void>((resolveSlot, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new Error(\"aborted\"));\n return;\n }\n const ready = () => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolveSlot();\n };\n const onAbort = () => {\n const index = waiters.indexOf(ready);\n if (index >= 0) waiters.splice(index, 1);\n reject(signal?.reason ?? new Error(\"aborted\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n waiters.push(ready);\n });\n // The releasing caller transferred its slot; `active` already counts it.\n return releaser();\n },\n active: () => active,\n waiting: () => waiters.length,\n };\n}\n\nconst processSlots = createSlotSemaphore(PROTON_PASS_MAX_PROCESSES);\nfunction acquireProcessSlot(signal?: AbortSignal): Promise<() => void> {\n return processSlots.acquire(signal);\n}\n\nconst liveStateDirs = new Set<string>();\nlet exitHookInstalled = false;\nfunction trackStateDir(dir: string) {\n liveStateDirs.add(dir);\n if (exitHookInstalled) return;\n exitHookInstalled = true;\n process.once(\"exit\", () => {\n for (const path of liveStateDirs) {\n try {\n rmSync(path, { recursive: true, force: true });\n } catch {\n // Best effort at exit.\n }\n }\n });\n}\n\n// --- helpers -------------------------------------------------------------------\n\nfunction unavailable(message: string): VaultProviderError {\n return new VaultProviderError(\"provider_unavailable\", message);\n}\n\nfunction findOnPath(command: string, pathValue: string | undefined): string | null {\n for (const dir of (pathValue ?? \"\").split(delimiter)) {\n if (!dir || !isAbsolute(dir)) continue;\n const candidate = join(dir, command);\n try {\n accessSync(candidate, fsConstants.X_OK);\n if (statSync(candidate).isFile()) return candidate;\n } catch {\n // Not here.\n }\n }\n return null;\n}\n\nasync function sha256File(path: string): Promise<string> {\n const hash = createHash(\"sha256\");\n for await (const chunk of createReadStream(path)) hash.update(chunk as Buffer);\n return hash.digest(\"hex\");\n}\n\n/** Creates (or checks) a private directory owned by this process's user. */\nexport function ensurePrivateDirectory(path: string): void {\n mkdirSync(path, { recursive: true, mode: 0o700 });\n const stat = lstatSync(path);\n if (stat.isSymbolicLink() || !stat.isDirectory()) {\n throw unavailable(\"The Proton Pass state directory is not a private directory\");\n }\n const uid = process.getuid?.();\n if (uid !== undefined && stat.uid !== uid) {\n throw unavailable(\"The Proton Pass state directory is owned by another user\");\n }\n if ((stat.mode & 0o077) !== 0) chmodSync(path, 0o700);\n}\n\n/** A reason for Proton's agent audit log, built only from trusted identifiers. */\nexport function agentReason(subject: string, authority?: VaultProviderAuthority): string {\n const clean = (value: string) => value.replace(/[^A-Za-z0-9:._-]/g, \"\").slice(0, 64);\n const parts = [`Opengeni ${subject.replace(/[^A-Za-z0-9 ._-]/g, \"\")}`];\n if (authority) {\n parts.push(`workspace ${clean(authority.workspaceId)}`);\n if (authority.sessionId) parts.push(`session ${clean(authority.sessionId)}`);\n if (authority.turnId) parts.push(`turn ${clean(authority.turnId)}`);\n if (authority.subjectId) parts.push(`subject ${clean(authority.subjectId)}`);\n }\n return parts.join(\"; \").slice(0, PROTON_PASS_MAX_REASON_CHARS);\n}\n\nfunction succeeded(result: ProcessResult): boolean {\n return (\n result.exitCode === 0 &&\n result.signal === null &&\n !result.timedOut &&\n !result.aborted &&\n !result.stdoutOverflow &&\n result.spawnError === null\n );\n}\n\n/**\n * One logged-in pass-cli state for one personal access token. Every call is\n * serialized (pass-cli keeps a single SQLite session store per directory), the\n * session is renewed before Proton's 2 h limit, and the directory with its\n * encrypted session is wiped after idling or on close.\n */\nexport class ProtonCliSession {\n private readonly runner: ProcessRunner;\n private readonly now: () => number;\n private readonly hostEnv: Readonly<Record<string, string | undefined>>;\n private readonly encryptionKey = randomBytes(32).toString(\"hex\");\n private binary: Promise<string> | null = null;\n private dir: string | null = null;\n private loggedInAt: number | null = null;\n private info: ProtonSessionInfo | null = null;\n private queue: Promise<unknown> = Promise.resolve();\n private pending = 0;\n private idleTimer: ReturnType<typeof setTimeout> | null = null;\n private closed = false;\n\n constructor(\n private readonly token: string,\n private readonly options: ProtonCliOptions = {},\n ) {\n this.runner = options.runner ?? runProcess;\n this.now = options.now ?? Date.now;\n this.hostEnv = options.hostEnv ?? process.env;\n }\n\n /** The state directory while a session is open (tests and diagnostics). */\n get stateDirectory(): string | null {\n return this.dir;\n }\n\n get sessionInfo(): ProtonSessionInfo | null {\n return this.info;\n }\n\n /** Runs one pass-cli command after ensuring a fresh login; returns stdout. */\n run(command: ProtonCommand): Promise<string> {\n return this.serialize(async () => (await this.execute(command)).stdout);\n }\n\n /** Login state for `validate`: logs in when needed and returns the token identity. */\n ensureSession(signal?: AbortSignal): Promise<ProtonSessionInfo> {\n return this.serialize(async () => {\n await this.ensureLogin(signal);\n return this.info!;\n });\n }\n\n /** Allocates a private directory inside the session state for one download. */\n privateScratchDir(): string {\n const dir = this.requireDir();\n return mkdtempSync(join(dir, \"dl-\"));\n }\n\n /** Logs out (best effort) and wipes the state directory. */\n async close(): Promise<void> {\n this.closed = true;\n if (this.idleTimer) clearTimeout(this.idleTimer);\n this.idleTimer = null;\n await this.queue.catch(() => {});\n await this.teardown();\n }\n\n private serialize<T>(work: () => Promise<T>): Promise<T> {\n if (this.closed) return Promise.reject(unavailable(\"The Proton Pass connection is closed\"));\n this.pending += 1;\n if (this.idleTimer) clearTimeout(this.idleTimer);\n this.idleTimer = null;\n const run = this.queue.then(work, work);\n this.queue = run.then(\n () => undefined,\n () => undefined,\n );\n return run.finally(() => {\n this.pending -= 1;\n if (this.pending === 0 && !this.closed) this.armIdleClose();\n });\n }\n\n private armIdleClose() {\n if (this.dir === null) return;\n const idleMs = this.options.idleCloseMs ?? PROTON_PASS_IDLE_CLOSE_MS;\n this.idleTimer = setTimeout(() => {\n this.idleTimer = null;\n if (this.pending > 0 || this.closed) return;\n void this.serialize(() => this.teardown()).catch(() => {});\n }, idleMs);\n this.idleTimer.unref?.();\n }\n\n private async teardown(): Promise<void> {\n const dir = this.dir;\n if (!dir) return;\n if (this.loggedInAt !== null) {\n try {\n await this.spawn({ args: [\"logout\"], subject: \"sign out\" }, false, 10_000);\n } catch {\n // The directory wipe below removes the session either way.\n }\n }\n this.loggedInAt = null;\n this.info = null;\n this.dir = null;\n liveStateDirs.delete(dir);\n rmSync(dir, { recursive: true, force: true });\n }\n\n private requireDir(): string {\n if (this.dir) return this.dir;\n const root = resolve(this.options.stateRoot ?? join(tmpdir(), \"opengeni-protonpass\"));\n ensurePrivateDirectory(root);\n const dir = mkdtempSync(join(root, \"pp-\"));\n ensurePrivateDirectory(dir);\n trackStateDir(dir);\n this.dir = dir;\n return dir;\n }\n\n private sessionDir(): string {\n return join(this.requireDir(), \"session\");\n }\n\n private baseEnv(): Record<string, string> {\n const dir = this.requireDir();\n const env: Record<string, string> = {\n HOME: dir,\n TZ: \"UTC\",\n LANG: \"C.UTF-8\",\n LC_ALL: \"C.UTF-8\",\n PATH: \"/usr/bin:/bin\",\n PROTON_PASS_SESSION_DIR: this.sessionDir(),\n PROTON_PASS_KEY_PROVIDER: \"env\",\n PROTON_PASS_ENCRYPTION_KEY: this.encryptionKey,\n PROTON_PASS_DISABLE_TELEMETRY: \"1\",\n PROTON_PASS_NO_UPDATE_CHECK: \"1\",\n PASS_LOG_LEVEL: \"off\",\n };\n for (const name of PASSTHROUGH_ENV) {\n const value = this.hostEnv[name];\n if (value) env[name] = value;\n }\n return env;\n }\n\n private async resolveBinary(): Promise<string> {\n this.binary ??= (async () => {\n const configured = this.options.binaryPath;\n if (configured !== undefined && !isAbsolute(configured)) {\n throw unavailable(\"The pass-cli path must be absolute\");\n }\n const found = configured ?? findOnPath(\"pass-cli\", this.hostEnv.PATH);\n if (!found) throw unavailable(\"pass-cli is not installed on this Opengeni server\");\n let path: string;\n try {\n path = realpathSync(found);\n const stat = statSync(path);\n if (!stat.isFile()) throw new Error(\"not a file\");\n if ((stat.mode & 0o002) !== 0) {\n throw unavailable(\"pass-cli is world-writable; refusing to run it\");\n }\n accessSync(path, fsConstants.X_OK);\n } catch (error) {\n if (error instanceof VaultProviderError) throw error;\n throw unavailable(\"pass-cli is not an executable file\");\n }\n const expectedSha = this.options.expectedSha256?.toLowerCase();\n if (expectedSha && (await sha256File(path)) !== expectedSha) {\n throw unavailable(\"pass-cli does not match the configured SHA-256\");\n }\n const expected = this.options.expectedVersion ?? PROTON_PASS_CLI_VERSION;\n const result = await this.runner({\n file: path,\n args: [\"--version\"],\n env: { HOME: this.requireDir(), PATH: \"/usr/bin:/bin\", LANG: \"C.UTF-8\" },\n cwd: this.requireDir(),\n timeoutMs: 10_000,\n maxStdoutBytes: 4096,\n maxStderrBytes: 4096,\n });\n const version = /\\b(\\d+\\.\\d+\\.\\d+)\\b/.exec(result.stdout)?.[1];\n if (!succeeded(result) || !version) {\n throw unavailable(\"pass-cli --version failed\");\n }\n if (version !== expected) {\n throw unavailable(\n `pass-cli ${version} is not supported; install pass-cli ${expected} for this Opengeni release`,\n );\n }\n return path;\n })();\n this.binary.catch(() => {\n this.binary = null;\n });\n return this.binary;\n }\n\n private async spawn(\n command: Pick<\n ProtonCommand,\n \"args\" | \"stdin\" | \"subject\" | \"authority\" | \"signal\" | \"maxStdoutBytes\"\n >,\n withToken: boolean,\n timeoutMs?: number,\n ): Promise<ProcessResult> {\n const file = await this.resolveBinary();\n const env = this.baseEnv();\n if (withToken) env.PROTON_PASS_PERSONAL_ACCESS_TOKEN = this.token;\n else env.PROTON_PASS_AGENT_REASON = agentReason(command.subject, command.authority);\n const release = await acquireProcessSlot(command.signal);\n try {\n return await this.runner({\n file,\n args: command.args,\n env,\n cwd: this.requireDir(),\n ...(command.stdin !== undefined ? { stdin: command.stdin } : {}),\n timeoutMs: timeoutMs ?? this.options.commandTimeoutMs ?? PROTON_PASS_COMMAND_TIMEOUT_MS,\n maxStdoutBytes:\n command.maxStdoutBytes ?? this.options.maxStdoutBytes ?? PROTON_PASS_MAX_STDOUT_BYTES,\n maxStderrBytes: MAX_STDERR_BYTES,\n ...(command.signal ? { signal: command.signal } : {}),\n });\n } finally {\n release();\n }\n }\n\n private sessionFresh(): boolean {\n if (this.loggedInAt === null || this.info === null) return false;\n const maxAge = this.options.sessionMaxAgeMs ?? PROTON_PASS_SESSION_MAX_AGE_MS;\n return this.now() - this.loggedInAt < maxAge;\n }\n\n private async ensureLogin(signal?: AbortSignal): Promise<void> {\n if (this.sessionFresh()) return;\n await this.login(signal);\n }\n\n private async login(signal?: AbortSignal): Promise<void> {\n this.loggedInAt = null;\n this.info = null;\n // A fresh login replaces any earlier session state in this directory.\n const sessionDir = this.sessionDir();\n rmSync(sessionDir, { recursive: true, force: true });\n mkdirSync(sessionDir, { mode: 0o700 });\n const result = await this.spawn(\n {\n args: [\"login\"],\n subject: \"sign in\",\n maxStdoutBytes: SMALL_STDOUT_BYTES,\n ...(signal ? { signal } : {}),\n },\n true,\n );\n if (!succeeded(result)) {\n signal?.throwIfAborted();\n throw loginFailure(result);\n }\n this.loggedInAt = this.now();\n const infoResult = await this.spawn(\n {\n args: [\"info\", \"--output\", \"json\"],\n subject: \"read session info\",\n maxStdoutBytes: SMALL_STDOUT_BYTES,\n ...(signal ? { signal } : {}),\n },\n false,\n );\n if (!succeeded(infoResult)) {\n this.loggedInAt = null;\n signal?.throwIfAborted();\n throw mapProtonFailure(infoResult, \"read session info\");\n }\n const parsed = InfoOutput.safeParse(parseJson(infoResult.stdout));\n if (!parsed.success) {\n this.loggedInAt = null;\n throw unavailable(\"pass-cli returned unexpected session info\");\n }\n if (parsed.data.username !== undefined) {\n // A personal access token login never reports a user name.\n this.loggedInAt = null;\n throw new VaultProviderError(\n \"provider_auth_invalid\",\n \"The Proton Pass session is not a personal access token session\",\n );\n }\n const tokenName = parsed.data.personal_access_token_name ?? null;\n this.info = {\n tokenName: tokenName?.replace(/^\\[Agent\\] /, \"\") ?? null,\n agent: tokenName?.startsWith(\"[Agent] \") ?? false,\n };\n }\n\n private async execute(command: ProtonCommand): Promise<ProcessResult> {\n command.signal?.throwIfAborted();\n await this.ensureLogin(command.signal);\n let result = await this.spawn(command, false);\n if (!succeeded(result) && !result.timedOut && !result.aborted) {\n if (NOT_AUTHENTICATED.test(result.stderr)) {\n // Pre-flight: nothing reached Proton, so one relogin and retry is safe for writes too.\n await this.login(command.signal);\n result = await this.spawn(command, false);\n } else if (SESSION_INVALIDATED.test(result.stderr)) {\n this.loggedInAt = null;\n this.info = null;\n if (command.mutationContext) throw outcomeUnknown(command.subject);\n await this.login(command.signal);\n result = await this.spawn(command, false);\n }\n }\n if (succeeded(result)) return result;\n if (SESSION_INVALIDATED.test(result.stderr) || NOT_AUTHENTICATED.test(result.stderr)) {\n this.loggedInAt = null;\n this.info = null;\n }\n if (command.mutationContext) {\n if (!isDefiniteMutationFailure(result, command.mutationContext)) {\n throw outcomeUnknown(command.subject);\n }\n throw mapProtonFailure(result, command.subject);\n }\n if (result.aborted) command.signal?.throwIfAborted();\n if (result.stdoutOverflow) {\n throw new VaultProviderError(\n command.overflowCode ?? \"provider_unavailable\",\n `Proton Pass returned more data than Opengeni reads at once (${command.subject})`,\n );\n }\n throw mapProtonFailure(result, command.subject);\n }\n}\n\nexport function parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n","import { VaultProviderError } from \"./contract\";\nimport type { ProcessResult } from \"./runner\";\n\n/**\n * pass-cli 2.4.2 prints anyhow errors as `Error: <context>\\n\\nCaused by:\\n …`.\n * API failures surface as `Could not perform operation. Reason: <ProtonApiErrorCode>`\n * (pass/src/macros.rs `assert_response!`) or `Invalid status code: <status>`.\n * The reason form appears whenever a non-2xx body carries a `Code` that\n * pass/src/error.rs `ProtonApiErrorCode` knows, whatever the HTTP status, so\n * a reason alone does not prove a 4xx; the status form appears otherwise.\n * stderr is never returned to callers; only the classification below is.\n */\nconst REASON = /Could not perform operation\\. Reason: ([A-Za-z]+)/;\nconst STATUS = /Invalid status code(?: for download chunk)?: (\\d{3})/;\n\n/** The session can no longer be used; a fresh login is required. */\nexport const SESSION_INVALIDATED = /Your session has been invalidated/;\n/** Pre-flight: the CLI found no usable session before contacting the API. */\nexport const NOT_AUTHENTICATED = /This operation requires an authenticated client/;\n\nconst NOT_FOUND =\n /Item not found|Share with id \\S+ not found|Could not find vault|Could not find item|Attachment not found/;\nconst NETWORK =\n /error sending request|dns error|failed to lookup address|Connection refused|connection (?:reset|closed)|operation timed out|tcp connect error|certificate/i;\n\nconst PERMISSION_REASONS = new Set([\n \"PermissionDenied\",\n \"NotAllowed\",\n \"InsufficientScope\",\n \"AdminPermissionMissing\",\n \"Banned\",\n \"FeatureDisabled\",\n]);\nconst NOT_FOUND_REASONS = new Set([\"NotExists\", \"DeletedShare\"]);\nconst CONFLICT_REASONS = new Set([\"NotLatestRevision\", \"NotLatestKey\", \"AlreadyExists\"]);\nconst QUOTA_REASONS = new Set([\"NoQuotaLeft\", \"ResourceLimitExceeded\", \"PayloadTooLarge\"]);\n\n/** The Proton API error code name in stderr, if any (a closed enum, safe to report). */\nexport function protonReason(stderr: string): string | null {\n return REASON.exec(stderr)?.[1] ?? null;\n}\n\nexport function protonStatus(stderr: string): number | null {\n const match = STATUS.exec(stderr);\n return match ? Number(match[1]) : null;\n}\n\n/**\n * Statuses with which Proton refuses a request before applying it: a bad or\n * invalid request (400, 422), an unauthorised or forbidden one (401, 403), a\n * missing target (404), a conflict (409), an oversized payload (413) or\n * throttling (429). Any other status (500, 502, 503, 504 from Proton or a\n * proxy, or anything unexpected) may follow an applied change.\n */\nexport const PROTON_DEFINITE_REJECTION_STATUSES: ReadonlySet<number> = new Set([\n 400, 401, 403, 404, 409, 413, 422, 429,\n]);\n\n/**\n * `ProtonApiErrorCode` names (pass-cli 2.4.2 pass/src/error.rs) that describe\n * a refusal of the request itself: permission, a missing or deleted target, a\n * stale revision or key, a lock, a quota, or invalid input. Server-side\n * failures that may follow a partial write (`Timeout`, `InsertFailed`,\n * `SelectFailed`, `UploadFailure`, the `Provider*` family) and any name not\n * listed here leave a mutation's outcome unknown.\n */\nexport const PROTON_DEFINITE_REJECTION_REASONS: ReadonlySet<string> = new Set([\n ...PERMISSION_REASONS,\n ...NOT_FOUND_REASONS,\n ...CONFLICT_REASONS,\n ...QUOTA_REASONS,\n \"SessionLocked\",\n \"IsLocked\",\n \"InvalidSignature\",\n \"MissingKeys\",\n \"RotationPayloadIncomplete\",\n \"IncompatibleState\",\n \"BadLockId\",\n \"InvalidRequirements\",\n \"InvalidValue\",\n \"InvalidType\",\n \"ValueOutOfBounds\",\n \"NotNull\",\n \"NotEmpty\",\n \"NotTrue\",\n \"NotFalse\",\n \"NotEqual\",\n \"Equal\",\n \"NotSameAsField\",\n \"RegexError\",\n \"InvalidNumber\",\n \"InvalidLength\",\n \"TooShort\",\n \"TooLong\",\n \"HashNotEqual\",\n \"EmailFormat\",\n \"IpFormat\",\n \"UrlFormat\",\n \"CurrencyFormat\",\n \"LocaleFormat\",\n \"DateFormat\",\n \"JsonFormat\",\n \"MimeFormat\",\n \"PhoneFormat\",\n \"DomainFormat\",\n \"PgpFormat\",\n \"IdFormat\",\n \"HexFormat\",\n \"Base64Format\",\n \"VersionFormat\",\n \"ImageFormat\",\n]);\n\n/**\n * True when stderr shows Proton refused the request without applying it: a\n * known rejection reason, or (when no reason was decoded) a rejection status.\n */\nexport function isDefiniteRejection(stderr: string): boolean {\n const reason = protonReason(stderr);\n if (reason !== null) return PROTON_DEFINITE_REJECTION_REASONS.has(reason);\n const status = protonStatus(stderr);\n return status !== null && PROTON_DEFINITE_REJECTION_STATUSES.has(status);\n}\n\n/**\n * Maps a failed pass-cli run to a provider error. `subject` names the action in\n * the message (for example \"list items\"); stderr content never leaves here\n * except the closed Proton error-code name.\n */\nexport function mapProtonFailure(result: ProcessResult, subject: string): VaultProviderError {\n if (result.spawnError) {\n return new VaultProviderError(\"provider_unavailable\", \"pass-cli could not be started\");\n }\n if (result.timedOut) {\n return new VaultProviderError(\"provider_unavailable\", `Proton Pass timed out (${subject})`);\n }\n if (result.aborted) {\n return new VaultProviderError(\n \"provider_unavailable\",\n `Proton Pass call cancelled (${subject})`,\n );\n }\n const stderr = result.stderr;\n if (SESSION_INVALIDATED.test(stderr) || NOT_AUTHENTICATED.test(stderr)) {\n return new VaultProviderError(\n \"provider_auth_expired\",\n \"The Proton Pass session ended; sign in again with the personal access token\",\n );\n }\n const reason = protonReason(stderr);\n if (reason) {\n if (reason === \"SessionLocked\" || reason === \"IsLocked\") {\n return new VaultProviderError(\"provider_locked\", \"The Proton Pass session is locked\");\n }\n if (PERMISSION_REASONS.has(reason)) {\n return new VaultProviderError(\n \"provider_permission_denied\",\n `The Proton Pass token may not ${subject} (${reason})`,\n );\n }\n if (NOT_FOUND_REASONS.has(reason)) {\n return new VaultProviderError(\"provider_not_found\", \"No such Proton Pass vault or item\");\n }\n if (CONFLICT_REASONS.has(reason)) {\n return new VaultProviderError(\n \"provider_conflict\",\n `Proton Pass rejected the change because the item changed (${reason})`,\n );\n }\n if (QUOTA_REASONS.has(reason)) {\n return new VaultProviderError(\n \"provider_unavailable\",\n `Proton Pass refused the request: account limit reached (${reason})`,\n );\n }\n return new VaultProviderError(\n \"provider_unavailable\",\n `Proton Pass rejected the request (${reason})`,\n );\n }\n const status = protonStatus(stderr);\n if (status !== null) {\n if (status === 429) {\n return new VaultProviderError(\n \"provider_rate_limited\",\n \"Proton Pass is rate limiting\",\n 60_000,\n );\n }\n if (status === 401) {\n return new VaultProviderError(\"provider_auth_expired\", \"The Proton Pass session expired\");\n }\n if (status === 403) {\n return new VaultProviderError(\n \"provider_permission_denied\",\n `The Proton Pass token may not ${subject}`,\n );\n }\n if (status === 404) {\n return new VaultProviderError(\"provider_not_found\", \"No such Proton Pass vault or item\");\n }\n if (status === 409) {\n return new VaultProviderError(\"provider_conflict\", \"Proton Pass reported a conflict\");\n }\n return new VaultProviderError(\"provider_unavailable\", `Proton Pass returned HTTP ${status}`);\n }\n if (NOT_FOUND.test(stderr)) {\n return new VaultProviderError(\"provider_not_found\", \"No such Proton Pass vault or item\");\n }\n if (NETWORK.test(stderr)) {\n return new VaultProviderError(\"provider_unavailable\", \"Proton Pass could not be reached\");\n }\n return new VaultProviderError(\"provider_unavailable\", `Proton Pass could not ${subject}`);\n}\n\n/**\n * Markers proving a mutation failed before anything was sent: bad input, no\n * session, or the agent-reason check (`ensure_reason_if_agent`) that runs first.\n */\nconst PRE_FLIGHT =\n /Error parsing JSON|Error parsing template JSON|Error reading (?:from stdin|template)|Error converting template|requires an authenticated client|Agent sessions must set the PROTON_PASS_AGENT_REASON|PROTON_PASS_AGENT_REASON is (?:set but empty|too long)|Invalid field type|Invalid timestamp value|Please provide either|Error creating trash item request|Could not find vault|Share with id \\S+ not found/;\n\n/**\n * Whether a failed mutation is known not to have taken effect. Only a server\n * rejection inside the mutation's own error context (`Error creating …`,\n * `Error trashing item`) with a known rejection reason or status, or a\n * pre-flight marker, counts. A server error (500, 502, 503, 504 or any other\n * status or reason outside the rejection sets), a timeout, a signal, a\n * cancelled call or an error after the request (for example the agent monitor\n * event sent after a create) leaves the outcome unknown.\n */\nexport function isDefiniteMutationFailure(result: ProcessResult, mutationContext: RegExp): boolean {\n if (result.spawnError) return true;\n if (result.timedOut || result.aborted || result.signal !== null || result.stdoutOverflow) {\n return false;\n }\n if (result.exitCode === null) return false;\n const stderr = result.stderr;\n if (SESSION_INVALIDATED.test(stderr)) return false;\n if (PRE_FLIGHT.test(stderr)) return true;\n return mutationContext.test(stderr) && isDefiniteRejection(stderr);\n}\n\nexport function outcomeUnknown(subject: string): VaultProviderError {\n return new VaultProviderError(\n \"provider_outcome_unknown\",\n `Proton Pass may or may not have completed \"${subject}\"; check the vault before retrying`,\n );\n}\n\n/** pass-cli's context for a token login the API answered (`Error logging in with personal access token`). */\nconst LOGIN_CONTEXT = /Error logging in with personal access token/;\n/** Statuses with which Proton's API refuses the token itself. */\nconst LOGIN_REJECTED_STATUSES = new Set([400, 401, 403, 422]);\n\n/**\n * Maps a failed `pass-cli login`. Only Proton's own refusal of the token\n * (a 400, 401, 403 or 422 answer, or a permission or not-found reason, in\n * the token-login context) asks the customer for a new token. Local\n * failures (key provider, disk, an unexpected CLI error), network trouble,\n * throttling and server errors are `provider_unavailable` or\n * `provider_rate_limited`; reconnecting would not help with them.\n */\nexport function loginFailure(result: ProcessResult): VaultProviderError {\n const stderr = result.stderr;\n const answered =\n !result.spawnError && !result.timedOut && !result.aborted && LOGIN_CONTEXT.test(stderr);\n if (answered) {\n const status = protonStatus(stderr);\n const reason = protonReason(stderr);\n if (\n (status !== null && LOGIN_REJECTED_STATUSES.has(status)) ||\n (reason !== null && (PERMISSION_REASONS.has(reason) || NOT_FOUND_REASONS.has(reason)))\n ) {\n return new VaultProviderError(\n \"provider_auth_invalid\",\n \"Proton Pass rejected the personal access token (revoked, expired or mistyped)\",\n );\n }\n }\n const mapped = mapProtonFailure(result, \"sign in\");\n // Outside the API's verdict on the token, no other mapping (expired\n // session, permission, not found) describes a failed login accurately.\n if (mapped.code === \"provider_rate_limited\") return mapped;\n if (mapped.code === \"provider_unavailable\") return mapped;\n return new VaultProviderError(\"provider_unavailable\", \"Proton Pass could not sign in\");\n}\n","import { spawn } from \"node:child_process\";\n\n/** One bounded subprocess run. No shell, no inherited environment. */\nexport interface ProcessRequest {\n file: string;\n args: readonly string[];\n env: Readonly<Record<string, string>>;\n cwd: string;\n stdin?: string;\n timeoutMs: number;\n maxStdoutBytes: number;\n maxStderrBytes: number;\n signal?: AbortSignal;\n}\n\nexport interface ProcessResult {\n exitCode: number | null;\n signal: NodeJS.Signals | null;\n stdout: string;\n stderr: string;\n timedOut: boolean;\n aborted: boolean;\n /** stdout exceeded its bound; the process was killed and stdout is incomplete. */\n stdoutOverflow: boolean;\n /** The binary could not be started (missing, not executable). */\n spawnError: string | null;\n}\n\nexport type ProcessRunner = (request: ProcessRequest) => Promise<ProcessResult>;\n\nconst KILL_GRACE_MS = 1_000;\n\n/**\n * Runs `file` with an argv array and an explicit environment. stdout is capped\n * (the process is killed past the cap), stderr is truncated, and the process\n * group is terminated on timeout or abort, so a hung CLI cannot outlive the call.\n */\nexport const runProcess: ProcessRunner = (request) =>\n new Promise<ProcessResult>((resolve) => {\n const stdout: Buffer[] = [];\n const stderr: Buffer[] = [];\n let stdoutBytes = 0;\n let stderrBytes = 0;\n let stdoutOverflow = false;\n let timedOut = false;\n let aborted = false;\n let settled = false;\n let killTimer: ReturnType<typeof setTimeout> | undefined;\n\n if (request.signal?.aborted) {\n resolve({\n exitCode: null,\n signal: null,\n stdout: \"\",\n stderr: \"\",\n timedOut: false,\n aborted: true,\n stdoutOverflow: false,\n spawnError: null,\n });\n return;\n }\n\n const child = spawn(request.file, [...request.args], {\n cwd: request.cwd,\n env: { ...request.env },\n shell: false,\n detached: process.platform !== \"win32\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n windowsHide: true,\n });\n\n const terminate = () => {\n if (child.exitCode !== null || child.signalCode !== null) return;\n const kill = (sig: NodeJS.Signals) => {\n try {\n if (child.pid !== undefined && process.platform !== \"win32\")\n process.kill(-child.pid, sig);\n else child.kill(sig);\n } catch {\n // Already gone.\n }\n };\n kill(\"SIGTERM\");\n killTimer ??= setTimeout(() => kill(\"SIGKILL\"), KILL_GRACE_MS);\n killTimer.unref?.();\n };\n\n const timer = setTimeout(() => {\n timedOut = true;\n terminate();\n }, request.timeoutMs);\n timer.unref?.();\n const onAbort = () => {\n aborted = true;\n terminate();\n };\n request.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n const finish = (\n result: Omit<ProcessResult, \"stdout\" | \"stderr\" | \"timedOut\" | \"aborted\" | \"stdoutOverflow\">,\n ) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n if (killTimer) clearTimeout(killTimer);\n request.signal?.removeEventListener(\"abort\", onAbort);\n resolve({\n ...result,\n stdout: Buffer.concat(stdout).toString(\"utf8\"),\n stderr: Buffer.concat(stderr).toString(\"utf8\"),\n timedOut,\n aborted,\n stdoutOverflow,\n });\n };\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n if (stdoutOverflow) return;\n stdoutBytes += chunk.length;\n if (stdoutBytes > request.maxStdoutBytes) {\n stdoutOverflow = true;\n terminate();\n return;\n }\n stdout.push(chunk);\n });\n child.stderr.on(\"data\", (chunk: Buffer) => {\n if (stderrBytes >= request.maxStderrBytes) return;\n const room = request.maxStderrBytes - stderrBytes;\n const kept = chunk.length > room ? chunk.subarray(0, room) : chunk;\n stderrBytes += kept.length;\n stderr.push(kept);\n });\n child.on(\"error\", (error: NodeJS.ErrnoException) => {\n finish({ exitCode: null, signal: null, spawnError: error.code ?? \"spawn_failed\" });\n });\n child.on(\"close\", (exitCode, signal) => {\n finish({ exitCode, signal, spawnError: null });\n });\n // A CLI that exits before reading stdin raises EPIPE; the exit status still decides.\n child.stdin.on(\"error\", () => {});\n child.stdin.end(request.stdin ?? \"\");\n });\n","import { createHmac, randomBytes, randomUUID } from \"node:crypto\";\nimport { VaultProviderError, type VaultProvider, type VaultProviderOperations } from \"./contract\";\nimport {\n type ProtonPassVaultProvider,\n type ProtonPassVaultProviderOptions,\n createProtonPassVaultProvider,\n protonPassCapabilities,\n} from \"./provider\";\nimport { FILE_FIELD_PREFIX } from \"./mapping\";\nimport { restrictToOperations } from \"./operations\";\n\nexport const PROTON_PASS_POOL_MAX_SESSIONS = 32;\nexport const PROTON_PASS_POOL_IDLE_MS = 15 * 60_000;\n/** Retry hint when every pooled session is busy. */\nexport const PROTON_PASS_POOL_BUSY_RETRY_MS = 5_000;\n\nexport type ProtonPassProviderPoolOptions = Omit<\n ProtonPassVaultProviderOptions,\n \"token\" | \"operations\"\n> & {\n /**\n * Hard limit on CLI sessions held at once. At the limit the least recently\n * used idle session is logged out; when every session is busy the call is\n * refused with `provider_rate_limited` instead of growing the pool.\n */\n maxSessions?: number;\n /** A session unused this long is logged out, wiped and forgotten (token included). */\n poolIdleMs?: number;\n /** Builds one session's provider (tests). */\n create?: (options: ProtonPassVaultProviderOptions) => ProtonPassVaultProvider;\n};\n\nexport type ProtonPassPoolProviderOptions = {\n /**\n * The session scope, normally the Opengeni connection id. Providers with\n * the same connection id and token share one logged-in CLI session. Without\n * it the provider gets its own scope: a session no other provider uses.\n */\n connectionId?: string;\n /** Operations verified at setup; the provider is narrowed to them. */\n operations?: VaultProviderOperations;\n};\n\nexport interface ProtonPassProviderPool {\n /**\n * A provider for one connection's token. Sessions are never shared across\n * connections, even for the same token, nor across tokens: each has its own\n * CLI login, state directory, key and cache. The session is created on the\n * first call, not here.\n */\n provider(token: string, options?: ProtonPassPoolProviderOptions): VaultProvider;\n /** Logs every session out and wipes their state directories; later calls are refused. */\n close(): Promise<void>;\n /** Sessions currently held (tests and diagnostics). */\n size(): number;\n}\n\ntype Entry = {\n provider: ProtonPassVaultProvider;\n scope: string;\n lastUsed: number;\n active: number;\n};\n\n/**\n * A process-wide pool of Proton Pass CLI sessions. Logging in creates a\n * Proton session, so each connection logs in once and its session is reused\n * until it goes idle. Entries are keyed by an HMAC of scope and token under a\n * random per-pool key, so the map holds no token-derived value that outlives\n * the process.\n */\nexport function createProtonPassProviderPool(\n options: ProtonPassProviderPoolOptions,\n): ProtonPassProviderPool {\n const {\n maxSessions = PROTON_PASS_POOL_MAX_SESSIONS,\n poolIdleMs = PROTON_PASS_POOL_IDLE_MS,\n create = createProtonPassVaultProvider,\n ...providerOptions\n } = options;\n if (!Number.isInteger(maxSessions) || maxSessions < 1) {\n throw new RangeError(\"maxSessions must be a positive integer\");\n }\n const now = providerOptions.now ?? Date.now;\n const key = randomBytes(32);\n const entries = new Map<string, Entry>();\n let sweeper: ReturnType<typeof setInterval> | null = null;\n let closed = false;\n\n function retire(id: string, entry: Entry) {\n entries.delete(id);\n void entry.provider.close().catch(() => {});\n if (entries.size === 0 && sweeper) {\n clearInterval(sweeper);\n sweeper = null;\n }\n }\n\n function sweep() {\n const at = now();\n for (const [id, entry] of entries) {\n if (entry.active === 0 && at - entry.lastUsed >= poolIdleMs) retire(id, entry);\n }\n }\n\n function evictForRoom() {\n while (entries.size >= maxSessions) {\n let oldest: [string, Entry] | null = null;\n for (const pair of entries) {\n if (pair[1].active > 0) continue;\n if (!oldest || pair[1].lastUsed < oldest[1].lastUsed) oldest = pair;\n }\n if (!oldest) return;\n retire(oldest[0], oldest[1]);\n }\n }\n\n function entryFor(scope: string, token: string): Entry {\n if (closed) {\n throw new VaultProviderError(\n \"provider_unavailable\",\n \"The Proton Pass session pool is closed\",\n );\n }\n const id = createHmac(\"sha256\", key)\n .update(JSON.stringify([scope, token]))\n .digest(\"hex\");\n sweep();\n const existing = entries.get(id);\n if (existing) return existing;\n // A new token for this scope (rotation): its old idle sessions go now.\n for (const [otherId, other] of entries) {\n if (other.scope === scope && other.active === 0) retire(otherId, other);\n }\n evictForRoom();\n if (entries.size >= maxSessions) {\n throw new VaultProviderError(\n \"provider_rate_limited\",\n \"Every Proton Pass CLI session on this server is busy; try again shortly\",\n PROTON_PASS_POOL_BUSY_RETRY_MS,\n );\n }\n const entry: Entry = {\n provider: create({ ...providerOptions, token }),\n scope,\n lastUsed: now(),\n active: 0,\n };\n entries.set(id, entry);\n if (!sweeper) {\n sweeper = setInterval(sweep, Math.max(1_000, Math.min(poolIdleMs, 60_000)));\n sweeper.unref?.();\n }\n return entry;\n }\n\n function tracked(scope: string, token: string): VaultProvider {\n const run = async <T>(work: (provider: ProtonPassVaultProvider) => Promise<T>): Promise<T> => {\n const entry = entryFor(scope, token);\n entry.active += 1;\n entry.lastUsed = now();\n try {\n return await work(entry.provider);\n } finally {\n entry.active -= 1;\n entry.lastUsed = now();\n }\n };\n return {\n id: \"protonpass\",\n capabilities: protonPassCapabilities,\n validate: (ctx) => run((provider) => provider.validate(ctx)),\n listVaults: (ctx) => run((provider) => provider.listVaults(ctx)),\n listItems: (ctx, vaultId) => run((provider) => provider.listItems(ctx, vaultId)),\n readFields: (ctx, vaultId, itemId, fieldIds) =>\n run((provider) => provider.readFields(ctx, vaultId, itemId, fieldIds)),\n writeItem: (ctx, vaultId, item) => run((provider) => provider.writeItem(ctx, vaultId, item)),\n archiveItem: (ctx, vaultId, itemId) =>\n run((provider) => provider.archiveItem(ctx, vaultId, itemId)),\n };\n }\n\n return {\n provider(token, { connectionId, operations } = {}) {\n const scope =\n connectionId === undefined ? `standalone:${randomUUID()}` : `connection:${connectionId}`;\n return restrictToOperations(tracked(scope, token), operations, FILE_FIELD_PREFIX);\n },\n async close() {\n closed = true;\n if (sweeper) clearInterval(sweeper);\n sweeper = null;\n const all = [...entries.values()];\n entries.clear();\n await Promise.all(all.map((entry) => entry.provider.close().catch(() => {})));\n },\n size: () => entries.size,\n };\n}\n"],"mappings":"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","names":["lstatSync","rmSync","join","resolve","join","lstatSync","rmSync","randomBytes","randomBytes"]}
@@ -0,0 +1,41 @@
1
+ import { type ProviderFieldMeta, type ProviderItemMeta, type VaultItemType } from "./contract.js";
2
+ import type { Attachment, Item } from "./schema.js";
3
+ /**
4
+ * External field ids. They are positional names, not upstream ids: Proton
5
+ * items have no per-field identifiers, so ids are derived from the field's
6
+ * place in the item (`login.password`, `x:<extra field name>`,
7
+ * `s:<section>/<field>`, `@file:<attachment id>`), with `#n` for repeats.
8
+ */
9
+ export declare const NOTE_FIELD_ID = "@note";
10
+ export declare const FILE_FIELD_PREFIX = "@file:";
11
+ export declare const LOGIN_FIELD_IDS: {
12
+ readonly username: "login.username";
13
+ readonly email: "login.email";
14
+ readonly password: "login.password";
15
+ readonly totp: "login.totp";
16
+ };
17
+ export declare const TOTP_FIELD_NAME = "one-time password";
18
+ export type MappedValue = {
19
+ type: "text";
20
+ value: string;
21
+ } | {
22
+ type: "totp";
23
+ uri: string;
24
+ } | {
25
+ type: "file";
26
+ attachment: Attachment;
27
+ };
28
+ export interface MappedField extends ProviderFieldMeta {
29
+ value: MappedValue;
30
+ }
31
+ export interface MappedItem {
32
+ meta: ProviderItemMeta;
33
+ fields: MappedField[];
34
+ }
35
+ export declare function itemTypeForVariant(variant: string): VaultItemType;
36
+ /** Proton summary `item_type` (snake case) to an Opengeni item type. */
37
+ export declare function itemTypeForSummary(itemType: string): VaultItemType;
38
+ /** `YYYY-MM-DDTHH:MM:SS` (UTC under TZ=UTC) to an ISO instant. */
39
+ export declare function civilToIso(civil: string): string | null;
40
+ /** Maps an item (and, from `item view`, its attachments) to fields and metadata. */
41
+ export declare function mapItem(item: Item, attachments?: readonly Attachment[]): MappedItem;
@@ -0,0 +1,8 @@
1
+ import { type TotpParams } from "./contract.js";
2
+ export declare function nameKey(name: string): string;
3
+ export declare function safeSecretName(raw: string, fallback: string): string;
4
+ export declare function safeFieldName(raw: string, fallback: string): string;
5
+ /** Appends " (2)", " (3)" … so names are unique case-insensitively. */
6
+ export declare function uniqueName(name: string, taken: Set<string>): string;
7
+ /** A canonical otpauth URI for a parsed seed, for stores that require URIs. */
8
+ export declare function totpUri(params: TotpParams, label: string): string;
@@ -0,0 +1,7 @@
1
+ import { type VaultProvider, type VaultProviderOperations } from "./contract.js";
2
+ /**
3
+ * Narrows an adapter to the operations verified when its connection was set
4
+ * up: what it reports and what it will do. It never widens the adapter's own
5
+ * operations, and refused calls make no provider request.
6
+ */
7
+ export declare function restrictToOperations<P extends VaultProvider>(provider: P, verified: VaultProviderOperations | undefined, fileFieldPrefix: string): P;
package/dist/pool.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ import { type VaultProvider, type VaultProviderOperations } from "./contract.js";
2
+ import { type ProtonPassVaultProvider, type ProtonPassVaultProviderOptions } from "./provider.js";
3
+ export declare const PROTON_PASS_POOL_MAX_SESSIONS = 32;
4
+ export declare const PROTON_PASS_POOL_IDLE_MS: number;
5
+ /** Retry hint when every pooled session is busy. */
6
+ export declare const PROTON_PASS_POOL_BUSY_RETRY_MS = 5000;
7
+ export type ProtonPassProviderPoolOptions = Omit<ProtonPassVaultProviderOptions, "token" | "operations"> & {
8
+ /**
9
+ * Hard limit on CLI sessions held at once. At the limit the least recently
10
+ * used idle session is logged out; when every session is busy the call is
11
+ * refused with `provider_rate_limited` instead of growing the pool.
12
+ */
13
+ maxSessions?: number;
14
+ /** A session unused this long is logged out, wiped and forgotten (token included). */
15
+ poolIdleMs?: number;
16
+ /** Builds one session's provider (tests). */
17
+ create?: (options: ProtonPassVaultProviderOptions) => ProtonPassVaultProvider;
18
+ };
19
+ export type ProtonPassPoolProviderOptions = {
20
+ /**
21
+ * The session scope, normally the Opengeni connection id. Providers with
22
+ * the same connection id and token share one logged-in CLI session. Without
23
+ * it the provider gets its own scope: a session no other provider uses.
24
+ */
25
+ connectionId?: string;
26
+ /** Operations verified at setup; the provider is narrowed to them. */
27
+ operations?: VaultProviderOperations;
28
+ };
29
+ export interface ProtonPassProviderPool {
30
+ /**
31
+ * A provider for one connection's token. Sessions are never shared across
32
+ * connections, even for the same token, nor across tokens: each has its own
33
+ * CLI login, state directory, key and cache. The session is created on the
34
+ * first call, not here.
35
+ */
36
+ provider(token: string, options?: ProtonPassPoolProviderOptions): VaultProvider;
37
+ /** Logs every session out and wipes their state directories; later calls are refused. */
38
+ close(): Promise<void>;
39
+ /** Sessions currently held (tests and diagnostics). */
40
+ size(): number;
41
+ }
42
+ /**
43
+ * A process-wide pool of Proton Pass CLI sessions. Logging in creates a
44
+ * Proton session, so each connection logs in once and its session is reused
45
+ * until it goes idle. Entries are keyed by an HMAC of scope and token under a
46
+ * random per-pool key, so the map holds no token-derived value that outlives
47
+ * the process.
48
+ */
49
+ export declare function createProtonPassProviderPool(options: ProtonPassProviderPoolOptions): ProtonPassProviderPool;
@@ -0,0 +1,38 @@
1
+ import { type ProviderWriteItem, type VaultProvider, type VaultProviderCapabilities, type VaultProviderOperations } from "./contract.js";
2
+ import { type Item } from "./schema.js";
3
+ import { type ProtonCliOptions } from "./session.js";
4
+ export declare const PROTON_PASS_VALUE_CACHE_MS: 60000;
5
+ /** Agent tokens cannot list with secrets, so each item is viewed; bound that fan-out. */
6
+ export declare const PROTON_PASS_MAX_ITEM_VIEWS_PER_LIST = 500;
7
+ /** Operations pass-cli 2.4.2 supports without secrets on argv (see README). */
8
+ export declare const PROTON_PASS_OPERATIONS: VaultProviderOperations;
9
+ /** The adapter's capabilities; the same for every token (the PAT scope is enforced upstream). */
10
+ export declare function protonPassCapabilities(): VaultProviderCapabilities;
11
+ export type ProtonPassVaultProviderOptions = ProtonCliOptions & {
12
+ /** Operations verified at setup; the adapter narrows to them and never widens. */
13
+ operations?: VaultProviderOperations;
14
+ /** Personal access token `pst_…::…`, scoped by the customer to vaults or items. */
15
+ token: string;
16
+ valueCacheMs?: number;
17
+ maxItemViewsPerList?: number;
18
+ };
19
+ export type ProtonPassVaultProvider = VaultProvider & {
20
+ readonly id: "protonpass";
21
+ /** Logs the CLI session out and wipes its private state directory. */
22
+ close(): Promise<void>;
23
+ };
24
+ type CreatePlan = {
25
+ kind: "login" | "note" | "custom";
26
+ template: Record<string, unknown>;
27
+ /** The same content as an Item, for metadata when the follow-up read fails. */
28
+ synthetic: Item["content"]["content"];
29
+ note: string;
30
+ extraSections: Array<{
31
+ section_name: string;
32
+ section_fields: Item["content"]["extra_fields"];
33
+ }>;
34
+ };
35
+ /** Builds the `--from-template -` JSON for a create; values travel only on stdin. */
36
+ export declare function planCreate(item: ProviderWriteItem): CreatePlan;
37
+ export declare function createProtonPassVaultProvider(options: ProtonPassVaultProviderOptions): ProtonPassVaultProvider;
38
+ export {};
@@ -0,0 +1,31 @@
1
+ /** One bounded subprocess run. No shell, no inherited environment. */
2
+ export interface ProcessRequest {
3
+ file: string;
4
+ args: readonly string[];
5
+ env: Readonly<Record<string, string>>;
6
+ cwd: string;
7
+ stdin?: string;
8
+ timeoutMs: number;
9
+ maxStdoutBytes: number;
10
+ maxStderrBytes: number;
11
+ signal?: AbortSignal;
12
+ }
13
+ export interface ProcessResult {
14
+ exitCode: number | null;
15
+ signal: NodeJS.Signals | null;
16
+ stdout: string;
17
+ stderr: string;
18
+ timedOut: boolean;
19
+ aborted: boolean;
20
+ /** stdout exceeded its bound; the process was killed and stdout is incomplete. */
21
+ stdoutOverflow: boolean;
22
+ /** The binary could not be started (missing, not executable). */
23
+ spawnError: string | null;
24
+ }
25
+ export type ProcessRunner = (request: ProcessRequest) => Promise<ProcessResult>;
26
+ /**
27
+ * Runs `file` with an argv array and an explicit environment. stdout is capped
28
+ * (the process is killed past the cap), stderr is truncated, and the process
29
+ * group is terminated on timeout or abort, so a hung CLI cannot outlive the call.
30
+ */
31
+ export declare const runProcess: ProcessRunner;