@aopslabs/aops 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/LICENSE +19 -0
  2. package/NOTICE +7 -0
  3. package/README.md +203 -0
  4. package/assets/agent-assets/core/SKILL.md +49 -0
  5. package/assets/agent-assets/core/references/agentspace/SKILL.md +78 -0
  6. package/assets/agent-assets/core/references/aops-cli-core/SKILL.md +108 -0
  7. package/assets/agent-assets/core/references/chatv3/SKILL.md +48 -0
  8. package/assets/agent-assets/core/references/collaborative-work/SKILL.md +85 -0
  9. package/assets/agent-assets/core/references/discuss/SKILL.md +66 -0
  10. package/assets/agent-assets/core/references/docman/SKILL.md +69 -0
  11. package/assets/agent-assets/core/references/hosted-chat/SKILL.md +64 -0
  12. package/assets/agent-assets/core/references/mission/SKILL.md +54 -0
  13. package/assets/agent-assets/core/references/projectman/SKILL.md +86 -0
  14. package/assets/agent-assets/core/references/sys/SKILL.md +36 -0
  15. package/assets/agent-assets/core/references/view/SKILL.md +58 -0
  16. package/assets/agent-assets/core/references/working-disciplines/SKILL.md +69 -0
  17. package/assets/agent-assets/core/user-guides/agent-assets.md +81 -0
  18. package/assets/agent-assets/core/user-guides/agentspace.md +1098 -0
  19. package/assets/agent-assets/core/user-guides/aops-cli.md +1107 -0
  20. package/assets/agent-assets/core/user-guides/aops-system.md +63 -0
  21. package/assets/agent-assets/core/user-guides/chatv3.md +113 -0
  22. package/assets/agent-assets/core/user-guides/docman.md +162 -0
  23. package/assets/agent-assets/core/user-guides/projectman.md +212 -0
  24. package/assets/agent-assets/core/user-guides/sys.md +94 -0
  25. package/assets/agent-assets/core/user-guides/working-disciplines.md +588 -0
  26. package/assets/agent-assets/gateway/aops/SKILL.md +14 -0
  27. package/assets/r6-remote-session-baseline.json +19 -0
  28. package/assets/skills/aops-install/SKILL.md +231 -0
  29. package/assets/skills/aops-install/agents/openai.yaml +4 -0
  30. package/dist/commands/activity.js +352 -0
  31. package/dist/commands/agent-profile.js +653 -0
  32. package/dist/commands/agent.js +710 -0
  33. package/dist/commands/agents-md.js +125 -0
  34. package/dist/commands/api.js +84 -0
  35. package/dist/commands/archive.js +873 -0
  36. package/dist/commands/artifact.js +535 -0
  37. package/dist/commands/assets.js +1414 -0
  38. package/dist/commands/auth/device-login.js +1 -0
  39. package/dist/commands/auth/legacy-export.js +177 -0
  40. package/dist/commands/auth/login.js +426 -0
  41. package/dist/commands/chat.js +1363 -0
  42. package/dist/commands/chatv3.js +1684 -0
  43. package/dist/commands/checkpoint.js +549 -0
  44. package/dist/commands/commercial-artifact.js +475 -0
  45. package/dist/commands/commercial-license.js +594 -0
  46. package/dist/commands/community-auth.js +62 -0
  47. package/dist/commands/community-cockpit.js +185 -0
  48. package/dist/commands/community-console.js +109 -0
  49. package/dist/commands/community-doctor.js +335 -0
  50. package/dist/commands/community-server.js +2062 -0
  51. package/dist/commands/community-setup.js +284 -0
  52. package/dist/commands/discuss.js +1448 -0
  53. package/dist/commands/doc.js +5219 -0
  54. package/dist/commands/experience.js +922 -0
  55. package/dist/commands/host.js +1127 -0
  56. package/dist/commands/init.js +118 -0
  57. package/dist/commands/memory.js +3129 -0
  58. package/dist/commands/mission.js +562 -0
  59. package/dist/commands/official-catalog.js +134 -0
  60. package/dist/commands/plan.js +84 -0
  61. package/dist/commands/playbook.js +415 -0
  62. package/dist/commands/pm/context.js +6 -0
  63. package/dist/commands/pm/index.js +701 -0
  64. package/dist/commands/pm/projectman.js +6266 -0
  65. package/dist/commands/project.js +1080 -0
  66. package/dist/commands/prompt.js +1024 -0
  67. package/dist/commands/repo-sync.js +1907 -0
  68. package/dist/commands/resource.js +527 -0
  69. package/dist/commands/skill.js +1211 -0
  70. package/dist/commands/start-disciplines.js +510 -0
  71. package/dist/commands/start.js +1343 -0
  72. package/dist/commands/target.js +309 -0
  73. package/dist/commands/version.js +42 -0
  74. package/dist/commands/view.js +1852 -0
  75. package/dist/launchers/cockpit.js +28 -0
  76. package/dist/launchers/options.js +74 -0
  77. package/dist/launchers/server.js +41 -0
  78. package/dist/lib/agent-assets/envelope.js +83 -0
  79. package/dist/lib/agent-assets/gateway.js +15 -0
  80. package/dist/lib/agent-assets/guards.js +23 -0
  81. package/dist/lib/agent-assets/hosted-discovery.js +148 -0
  82. package/dist/lib/agent-assets/hosted-package-input.js +154 -0
  83. package/dist/lib/agent-assets/legacy-pointer-migration.js +677 -0
  84. package/dist/lib/agent-assets/native-fs.js +589 -0
  85. package/dist/lib/agent-assets/package-manifest.js +324 -0
  86. package/dist/lib/agent-assets/portable-path.js +67 -0
  87. package/dist/lib/agent-assets/release-input.js +177 -0
  88. package/dist/lib/agent-assets/roots.js +45 -0
  89. package/dist/lib/agent-assets/runtime-binding-reader.js +545 -0
  90. package/dist/lib/agent-assets/runtime-targets.js +50 -0
  91. package/dist/lib/agent-assets/store-reader.js +1212 -0
  92. package/dist/lib/agent-assets/store-types.js +1 -0
  93. package/dist/lib/agent-assets/store-writer.js +1484 -0
  94. package/dist/lib/agent-assets/types.js +1 -0
  95. package/dist/lib/agent-assets/unicode-case-folding-v15-1.generated.js +1548 -0
  96. package/dist/lib/commercial-final-readiness.js +504 -0
  97. package/dist/lib/commercial-lifecycle-smoke-isolation.js +236 -0
  98. package/dist/lib/commercial-managed-postgres-docker-adapter.js +274 -0
  99. package/dist/lib/commercial-setup-readiness-adapter.js +179 -0
  100. package/dist/lib/community-client-contract.js +164 -0
  101. package/dist/lib/community-cockpit-lifecycle.js +601 -0
  102. package/dist/lib/community-command-abort.js +59 -0
  103. package/dist/lib/community-diagnostic.js +237 -0
  104. package/dist/lib/community-docker-adapter.js +498 -0
  105. package/dist/lib/community-home.js +31 -0
  106. package/dist/lib/community-instance-contract.js +148 -0
  107. package/dist/lib/community-instance-layout.js +97 -0
  108. package/dist/lib/community-lifecycle.js +1631 -0
  109. package/dist/lib/community-migration-snapshot.js +770 -0
  110. package/dist/lib/community-native-application-recovery.js +425 -0
  111. package/dist/lib/community-native-child.js +240 -0
  112. package/dist/lib/community-native-database-recovery.js +456 -0
  113. package/dist/lib/community-native-lifecycle.js +2458 -0
  114. package/dist/lib/community-native-migration.js +339 -0
  115. package/dist/lib/community-native-postgres.js +596 -0
  116. package/dist/lib/community-operation-journal.js +773 -0
  117. package/dist/lib/community-operation-lock.js +596 -0
  118. package/dist/lib/community-release-resolver.js +291 -0
  119. package/dist/lib/community-release-verifier.js +475 -0
  120. package/dist/lib/community-repo-discovery.js +252 -0
  121. package/dist/lib/community-setup-server-env.js +203 -0
  122. package/dist/lib/external-url.js +110 -0
  123. package/dist/lib/official-catalog-gateway.js +108 -0
  124. package/dist/lib/official-catalog.js +364 -0
  125. package/dist/lib/server-bootstrap.js +240 -0
  126. package/dist/lib/setup-agent-assets-bridge.js +176 -0
  127. package/dist/lib/setup-agent-assets-release.js +52 -0
  128. package/dist/lib/setup-external-postgres.js +108 -0
  129. package/dist/lib/setup-init-orchestrator.js +990 -0
  130. package/dist/lib/setup-install-guide.js +52 -0
  131. package/dist/lib/setup-installer-release.js +47 -0
  132. package/dist/lib/setup-local-postgres.js +329 -0
  133. package/dist/lib/setup-official-catalog-bridge.js +148 -0
  134. package/dist/lib/setup-readiness.js +888 -0
  135. package/dist/lib/tui-launcher.js +59 -0
  136. package/dist/main.js +150 -0
  137. package/dist/seeds/agents-md.js +54 -0
  138. package/dist/utils/agent-gateway.js +275 -0
  139. package/dist/utils/agents-md.js +281 -0
  140. package/dist/utils/api.js +255 -0
  141. package/dist/utils/chatv3-session-store.js +185 -0
  142. package/dist/utils/command.js +67 -0
  143. package/dist/utils/community-host-runtime.js +376 -0
  144. package/dist/utils/config.js +1015 -0
  145. package/dist/utils/discussion-workspace.js +552 -0
  146. package/dist/utils/experience-workspace.js +326 -0
  147. package/dist/utils/guide-paths.js +67 -0
  148. package/dist/utils/hosted-sugar.js +56 -0
  149. package/dist/utils/hosted-workspace.js +229 -0
  150. package/dist/utils/memory-workspace.js +537 -0
  151. package/dist/utils/operator-runtime.js +199 -0
  152. package/dist/utils/password-crypto.js +39 -0
  153. package/dist/utils/playbook-workspace.js +479 -0
  154. package/dist/utils/project-context.js +255 -0
  155. package/dist/utils/prompts.js +70 -0
  156. package/dist/utils/refresh-race.js +28 -0
  157. package/dist/utils/repo-config.js +109 -0
  158. package/dist/utils/repo-first-projectman.js +194 -0
  159. package/dist/utils/repo-first-storage.js +13 -0
  160. package/dist/utils/repo-first-view.js +305 -0
  161. package/dist/utils/session-guidance.js +278 -0
  162. package/dist/utils/session-state.js +137 -0
  163. package/dist/utils/table.js +39 -0
  164. package/dist/utils/transient-fs.js +49 -0
  165. package/dist/utils/workspace-root.js +1 -0
  166. package/launchers/aops-cockpit.ps1 +15 -0
  167. package/launchers/aops-cockpit.sh +16 -0
  168. package/launchers/aops-server.ps1 +15 -0
  169. package/launchers/aops-server.sh +16 -0
  170. package/native/tui/win32-x64/aops-tui.exe +0 -0
  171. package/package.json +81 -0
@@ -0,0 +1,176 @@
1
+ export const SETUP_AGENT_ASSETS_CONTRACT = Object.freeze({
2
+ task: 'TASK-136',
3
+ surface: 'agent-assets-client-v1',
4
+ statusCommand: 'aops assets status --verify quick --json',
5
+ installCommand: 'aops assets install --target all --apply --json',
6
+ repairCommand: 'aops assets repair --repair-bindings --apply --json',
7
+ transitionRemovalCondition: 'Satisfied by the native TASK-136 provider composed after TASK-137; never route through setup agent-assets.',
8
+ });
9
+ export const SETUP_AGENT_ASSETS_GATEWAYS = Object.freeze({
10
+ codex: '<codex-home>/skills/aops/SKILL.md',
11
+ claude: '<claude-home>/skills/aops/SKILL.md',
12
+ });
13
+ export async function verifySetupAgentAssetsReleaseInput(verifyRelease, releaseRoot) {
14
+ return verifyRelease({ releaseRoot, verificationMode: 'offline' });
15
+ }
16
+ export function createSetupAgentAssetsProvider(dependencies = {}) {
17
+ const resolveRoots = dependencies.roots ?? resolveAgentAssetsRoots;
18
+ const readStatus = dependencies.readStatus ?? readAgentAssetsStoreStatus;
19
+ const inspectBindings = dependencies.inspectBindings ?? inspectRuntimeGatewayBindings;
20
+ const verifyRelease = dependencies.verifyRelease ?? verifyAndLoadCommunityCoreReleaseInput;
21
+ const applyCore = dependencies.applyCore ?? applyVerifiedCommunityCore;
22
+ const repairBindings = dependencies.repairBindings ?? repairAgentAssetRuntimeBindings;
23
+ const inspectLegacyPointers = dependencies.inspectLegacyPointers ?? inspectLegacyAopsPointers;
24
+ const migrateLegacyPointers = dependencies.migrateLegacyPointers ?? migrateLegacyAopsPointers;
25
+ const resolveRelease = dependencies.resolveRelease ?? resolveSetupAgentAssetsReleaseV1;
26
+ const inspect = async () => {
27
+ const roots = resolveRoots({});
28
+ const store = readStatus({ assetRoot: roots.assetRoot, verify: 'quick' });
29
+ const bindings = inspectBindings({
30
+ assetRoot: roots.assetRoot,
31
+ runtimeHomes: {
32
+ codex: roots.runtimeHomes.codex.absolutePath,
33
+ claude: roots.runtimeHomes.claude.absolutePath,
34
+ },
35
+ });
36
+ const states = AGENT_ASSET_RUNTIME_IDS.map((runtime) => bindings[runtime].state);
37
+ const recoveryReasons = store.recoveryReasons ?? [];
38
+ const storeDrift = recoveryReasons.length > 0;
39
+ const ready = store.state === 'ready' && !storeDrift && states.every((state) => state === 'ready');
40
+ const conflict = states.some((state) => state === 'ownership-conflict' || state === 'unsafe-path');
41
+ return Object.freeze({
42
+ availability: 'available',
43
+ state: ready ? 'ready' : conflict ? 'conflict' : 'action-required',
44
+ summary: ready
45
+ ? 'The verified AOPS core and all registered runtime gateways are ready.'
46
+ : conflict
47
+ ? 'A global runtime gateway has an ownership or unsafe-path conflict.'
48
+ : store.state === 'ready' && storeDrift
49
+ ? 'The verified AOPS core remains usable, but authenticated staging or receipt drift requires inspection.'
50
+ : store.state === 'ready'
51
+ ? 'The verified AOPS core is ready, but one or more runtime bindings require repair.'
52
+ : 'The verified global AOPS client core is not installed.',
53
+ nextActions: Object.freeze(ready
54
+ ? []
55
+ : conflict
56
+ ? ['Inspect `aops assets status --verify full --json`; unknown user files are never overwritten.']
57
+ : store.state === 'ready' && storeDrift
58
+ ? ['Inspect `aops assets status --verify full --json` and reconcile only the reported managed recovery state.']
59
+ : store.state === 'ready'
60
+ ? ['Run `aops assets repair --repair-bindings --apply --json`.']
61
+ : ['Run `aops assets install --target all --apply --json`.']),
62
+ data: Object.freeze({
63
+ store,
64
+ runtimeBindings: bindings,
65
+ recommendedAction: store.state === 'ready'
66
+ ? storeDrift ? 'inspect-recovery' : 'repair'
67
+ : 'install',
68
+ }),
69
+ });
70
+ };
71
+ return Object.freeze({
72
+ status: inspect,
73
+ async resolveRelease(options) {
74
+ return resolveRelease(options);
75
+ },
76
+ async apply(options) {
77
+ const roots = resolveRoots({});
78
+ const target = resolveAgentAssetTargetSelection(options.target);
79
+ const runtimeHomes = selectAgentAssetRuntimeHomes(target, {
80
+ codex: roots.runtimeHomes.codex.absolutePath,
81
+ claude: roots.runtimeHomes.claude.absolutePath,
82
+ });
83
+ if (options.action === 'install' || options.action === 'update') {
84
+ if (!options.fromRelease)
85
+ throw new Error('setup_init_agent_assets_release_required_for_install');
86
+ const release = await verifySetupAgentAssetsReleaseInput(verifyRelease, options.fromRelease);
87
+ const classifications = inspectLegacyPointers({ assetRoot: roots.assetRoot, runtimeHomes });
88
+ const conflicts = classifications.filter((item) => (item.state !== 'absent'
89
+ && item.state !== 'managed-ready'
90
+ && item.state !== 'recognized-legacy') || (item.state === 'recognized-legacy' && !item.eligible));
91
+ if (conflicts.length > 0) {
92
+ throw new Error(`setup_init_agent_assets_runtime_conflict:${conflicts.map((item) => `${item.runtime}:${item.state}`).join(',')}`);
93
+ }
94
+ const legacyRuntimes = new Set(classifications
95
+ .filter((item) => item.state === 'recognized-legacy')
96
+ .map((item) => item.runtime));
97
+ const directRuntimeHomes = Object.freeze(Object.fromEntries(target.runtimes
98
+ .filter((runtime) => !legacyRuntimes.has(runtime))
99
+ .map((runtime) => [runtime, runtimeHomes[runtime]])));
100
+ await applyCore({
101
+ assetRoot: roots.assetRoot,
102
+ release,
103
+ requestedOperation: options.action,
104
+ runtimeHomes: directRuntimeHomes,
105
+ });
106
+ if (legacyRuntimes.size > 0) {
107
+ await migrateLegacyPointers({
108
+ assetRoot: roots.assetRoot,
109
+ runtimeHomes: Object.freeze(Object.fromEntries(target.runtimes
110
+ .filter((runtime) => legacyRuntimes.has(runtime))
111
+ .map((runtime) => [runtime, runtimeHomes[runtime]]))),
112
+ });
113
+ }
114
+ }
115
+ else {
116
+ await repairBindings({
117
+ assetRoot: roots.assetRoot,
118
+ runtimeHomes,
119
+ });
120
+ }
121
+ return inspect();
122
+ },
123
+ });
124
+ }
125
+ function normalizeProviderStatus(status) {
126
+ if (status.availability !== 'available') {
127
+ throw new Error('setup_agent_assets_provider_contract_invalid');
128
+ }
129
+ return Object.freeze({
130
+ ...status,
131
+ nextActions: Object.freeze([...status.nextActions]),
132
+ data: Object.freeze({
133
+ ...status.data,
134
+ surface: SETUP_AGENT_ASSETS_CONTRACT.surface,
135
+ gatewayDestinations: SETUP_AGENT_ASSETS_GATEWAYS,
136
+ legacyRepoMirrorInstallerUsed: false,
137
+ }),
138
+ });
139
+ }
140
+ export async function inspectSetupAgentAssets(provider) {
141
+ if (!provider) {
142
+ return Object.freeze({
143
+ availability: 'task-136-pending',
144
+ state: 'action-required',
145
+ summary: 'The canonical global AOPS agent-assets client is not available in this build yet.',
146
+ nextActions: Object.freeze([
147
+ 'Complete TASK-136 on the TASK-137 merge base, then run `aops assets status --verify quick --json`.',
148
+ ]),
149
+ data: Object.freeze({
150
+ task: SETUP_AGENT_ASSETS_CONTRACT.task,
151
+ surface: SETUP_AGENT_ASSETS_CONTRACT.surface,
152
+ gatewayDestinations: SETUP_AGENT_ASSETS_GATEWAYS,
153
+ legacyRepoMirrorInstallerUsed: false,
154
+ transitionRemovalCondition: SETUP_AGENT_ASSETS_CONTRACT.transitionRemovalCondition,
155
+ }),
156
+ });
157
+ }
158
+ return normalizeProviderStatus(await provider.status());
159
+ }
160
+ export async function applySetupAgentAssets(provider, options) {
161
+ if (!provider?.apply) {
162
+ throw new Error('setup_init_agent_assets_contract_unavailable_task_136');
163
+ }
164
+ return normalizeProviderStatus(await provider.apply({
165
+ ...options,
166
+ target: 'all',
167
+ }));
168
+ }
169
+ import { verifyAndLoadCommunityCoreReleaseInput } from './agent-assets/release-input.js';
170
+ import { resolveAgentAssetsRoots } from './agent-assets/roots.js';
171
+ import { inspectRuntimeGatewayBindings } from './agent-assets/runtime-binding-reader.js';
172
+ import { readAgentAssetsStoreStatus } from './agent-assets/store-reader.js';
173
+ import { applyVerifiedCommunityCore, repairAgentAssetRuntimeBindings, } from './agent-assets/store-writer.js';
174
+ import { inspectLegacyAopsPointers, migrateLegacyAopsPointers, } from './agent-assets/legacy-pointer-migration.js';
175
+ import { resolveSetupAgentAssetsReleaseV1 } from './setup-agent-assets-release.js';
176
+ import { AGENT_ASSET_RUNTIME_IDS, resolveAgentAssetTargetSelection, selectAgentAssetRuntimeHomes, } from './agent-assets/runtime-targets.js';
@@ -0,0 +1,52 @@
1
+ import { lstatSync, realpathSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ import path from 'node:path';
4
+ import { resolveSetupOfficialCatalogReleaseV1, } from './setup-official-catalog-bridge.js';
5
+ function localAgentAssetsReleaseRoot(candidate) {
6
+ if (!candidate)
7
+ return undefined;
8
+ const releaseRoot = path.resolve(candidate);
9
+ try {
10
+ const root = lstatSync(releaseRoot);
11
+ if (!root.isDirectory() || root.isSymbolicLink())
12
+ return undefined;
13
+ for (const name of ['agent-assets-release.json', 'agent-assets-release.sigstore.json']) {
14
+ const entry = lstatSync(path.join(releaseRoot, name));
15
+ if (!entry.isFile() || entry.isSymbolicLink())
16
+ return undefined;
17
+ }
18
+ const assets = lstatSync(path.join(releaseRoot, 'agent-assets'));
19
+ if (!assets.isDirectory() || assets.isSymbolicLink())
20
+ return undefined;
21
+ return realpathSync.native(releaseRoot);
22
+ }
23
+ catch {
24
+ return undefined;
25
+ }
26
+ }
27
+ function defaultBundledCandidates() {
28
+ const moduleDirectory = path.dirname(fileURLToPath(import.meta.url));
29
+ return Object.freeze([
30
+ path.resolve(moduleDirectory, '..', 'agent-assets-release'),
31
+ path.resolve(moduleDirectory, '..', '..', 'agent-assets-release'),
32
+ ]);
33
+ }
34
+ export function resolveBundledAgentAssetsReleaseV1(dependencies = {}) {
35
+ for (const candidate of (dependencies.bundledCandidates ?? defaultBundledCandidates)()) {
36
+ const fromRelease = localAgentAssetsReleaseRoot(candidate);
37
+ if (fromRelease)
38
+ return Object.freeze({ fromRelease, source: 'bundled-npm' });
39
+ }
40
+ return undefined;
41
+ }
42
+ export async function resolveSetupAgentAssetsReleaseV1(options = {}, dependencies = {}) {
43
+ const bundled = resolveBundledAgentAssetsReleaseV1(dependencies);
44
+ if (bundled)
45
+ return bundled;
46
+ try {
47
+ return await (dependencies.fallback ?? resolveSetupOfficialCatalogReleaseV1)(options);
48
+ }
49
+ catch {
50
+ throw new Error('agent_assets_verified_source_unavailable:reinstall_the_official_aops_cli_package_or_use_--from-release_as_an_offline_override');
51
+ }
52
+ }
@@ -0,0 +1,108 @@
1
+ import { Client } from 'pg';
2
+ import { loadExternalPostgresUrl } from './community-native-lifecycle.js';
3
+ export class ExternalPostgresProbeError extends Error {
4
+ category;
5
+ constructor(code, category, options) {
6
+ super(code, options);
7
+ this.name = 'ExternalPostgresProbeError';
8
+ this.category = category;
9
+ }
10
+ }
11
+ export function isExternalPostgresTlsProbeError(error) {
12
+ return error instanceof ExternalPostgresProbeError && error.category === 'tls';
13
+ }
14
+ function safeProbeError(error) {
15
+ const record = error && typeof error === 'object' ? error : {};
16
+ const code = String(record.code ?? '');
17
+ const message = String(record.message ?? '').toLowerCase();
18
+ if (/ssl|tls|certificate|self[- ]signed|hostname|altname/.test(message) ||
19
+ ['CERT_HAS_EXPIRED', 'DEPTH_ZERO_SELF_SIGNED_CERT', 'ERR_TLS_CERT_ALTNAME_INVALID',
20
+ 'SELF_SIGNED_CERT_IN_CHAIN', 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
21
+ 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'].includes(code)) {
22
+ return new ExternalPostgresProbeError('setup_external_postgres_tls_connection_failed', 'tls', { cause: error });
23
+ }
24
+ if (code === '28P01' || code === '28000') {
25
+ return new ExternalPostgresProbeError('setup_external_postgres_auth_failed', 'auth', { cause: error });
26
+ }
27
+ if (code === '3D000') {
28
+ return new ExternalPostgresProbeError('setup_external_postgres_database_not_found', 'database', { cause: error });
29
+ }
30
+ if (['ECONNREFUSED', 'ECONNRESET', 'ENETUNREACH', 'ENOTFOUND', 'ETIMEDOUT'].includes(code)) {
31
+ return new ExternalPostgresProbeError('setup_external_postgres_unreachable', 'network', { cause: error });
32
+ }
33
+ return new ExternalPostgresProbeError('setup_external_postgres_connection_failed', 'unknown', { cause: error });
34
+ }
35
+ function prepareExternalPostgresUrl(value, tlsPolicy) {
36
+ let url;
37
+ try {
38
+ url = new URL(value);
39
+ }
40
+ catch {
41
+ throw new ExternalPostgresProbeError('setup_external_postgres_url_invalid', 'database');
42
+ }
43
+ if ((url.protocol !== 'postgres:' && url.protocol !== 'postgresql:') ||
44
+ !url.hostname || !url.username || !url.password || !url.pathname.slice(1)) {
45
+ throw new ExternalPostgresProbeError('setup_external_postgres_url_invalid', 'database');
46
+ }
47
+ if (url.hash) {
48
+ throw new ExternalPostgresProbeError('setup_external_postgres_url_options_refused', 'database');
49
+ }
50
+ url.search = '';
51
+ if (tlsPolicy === 'disable') {
52
+ url.searchParams.set('sslmode', 'disable');
53
+ }
54
+ else if (tlsPolicy === 'require') {
55
+ url.searchParams.set('sslmode', 'require');
56
+ url.searchParams.set('uselibpqcompat', 'true');
57
+ }
58
+ else if (tlsPolicy === 'verify-full') {
59
+ url.searchParams.set('sslmode', 'verify-full');
60
+ }
61
+ else {
62
+ throw new ExternalPostgresProbeError('setup_external_postgres_tls_policy_invalid', 'tls');
63
+ }
64
+ return url.toString();
65
+ }
66
+ export async function probeExternalPostgresConnection(options, dependencies = {}) {
67
+ const requestedTimeout = Number(options.timeoutMs ?? 10_000);
68
+ const timeoutMs = Number.isFinite(requestedTimeout)
69
+ ? Math.min(Math.max(requestedTimeout, 500), 30_000)
70
+ : 10_000;
71
+ if (Boolean(options.configRef) === Boolean(options.repoUrl)) {
72
+ throw new ExternalPostgresProbeError('setup_external_postgres_source_required', 'database');
73
+ }
74
+ const connectionString = options.repoUrl
75
+ ? prepareExternalPostgresUrl(options.repoUrl, options.tlsPolicy)
76
+ : loadExternalPostgresUrl(options.configRef, options.tlsPolicy);
77
+ const createClient = dependencies.createClient
78
+ ?? ((config) => new Client(config));
79
+ const client = createClient({
80
+ connectionString,
81
+ connectionTimeoutMillis: timeoutMs,
82
+ query_timeout: timeoutMs,
83
+ statement_timeout: timeoutMs,
84
+ });
85
+ try {
86
+ await client.connect();
87
+ const inspected = await client.query("SELECT current_setting('server_version_num') AS server_version_num");
88
+ const serverMajor = Math.floor(Number(inspected.rows[0]?.server_version_num) / 10_000);
89
+ if (!Number.isSafeInteger(serverMajor) || serverMajor < 1) {
90
+ throw new Error('postgres_server_version_invalid');
91
+ }
92
+ const encrypted = options.tlsPolicy !== 'disable';
93
+ return Object.freeze({
94
+ status: 'ready',
95
+ tlsPolicy: options.tlsPolicy,
96
+ transport: encrypted ? 'encrypted' : 'unencrypted',
97
+ serverMajor,
98
+ });
99
+ }
100
+ catch (error) {
101
+ if (error instanceof ExternalPostgresProbeError)
102
+ throw error;
103
+ throw safeProbeError(error);
104
+ }
105
+ finally {
106
+ await client.end().catch(() => undefined);
107
+ }
108
+ }