@ankhorage/infra 0.3.7 → 0.4.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.
- package/CHANGELOG.md +6 -0
- package/README.md +2 -1
- package/dist/adapters/minikube/base/index.d.ts.map +1 -1
- package/dist/adapters/minikube/base/index.js +8 -2
- package/dist/adapters/minikube/base/index.js.map +1 -1
- package/dist/adapters/minikube/index.d.ts.map +1 -1
- package/dist/adapters/minikube/index.js +8 -0
- package/dist/adapters/minikube/index.js.map +1 -1
- package/dist/adapters/minikube/secrets/index.d.ts +7 -0
- package/dist/adapters/minikube/secrets/index.d.ts.map +1 -0
- package/dist/adapters/minikube/secrets/index.js +13 -0
- package/dist/adapters/minikube/secrets/index.js.map +1 -0
- package/dist/adapters/minikube/secrets/supabase-vault/index.d.ts +8 -0
- package/dist/adapters/minikube/secrets/supabase-vault/index.d.ts.map +1 -0
- package/dist/adapters/minikube/secrets/supabase-vault/index.js +74 -0
- package/dist/adapters/minikube/secrets/supabase-vault/index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/secretStore.d.ts +19 -0
- package/dist/secretStore.d.ts.map +1 -0
- package/dist/secretStore.js +22 -0
- package/dist/secretStore.js.map +1 -0
- package/package.json +7 -3
- package/src/adapters/minikube/base/index.ts +9 -1
- package/src/adapters/minikube/index.ts +7 -0
- package/src/adapters/minikube/secrets/index.test.ts +103 -0
- package/src/adapters/minikube/secrets/index.ts +19 -0
- package/src/adapters/minikube/secrets/supabase-vault/index.ts +91 -0
- package/src/index.ts +5 -0
- package/src/package.test.ts +8 -1
- package/src/secretStore.test.ts +76 -0
- package/src/secretStore.ts +44 -0
|
@@ -2,6 +2,7 @@ import { generateApiInfrastructureArtifacts } from '../../apiArtifacts';
|
|
|
2
2
|
import { generateAuthProviderArtifacts } from './auth';
|
|
3
3
|
import { generateAuthorizationArtifacts } from './authz';
|
|
4
4
|
import { generateMinikubeBaseArtifacts } from './base';
|
|
5
|
+
import { generateSecretStoreArtifacts } from './secrets';
|
|
5
6
|
import { generateStorageArtifacts } from './storage';
|
|
6
7
|
const DEFAULT_NAMESPACE = 'ankh-app';
|
|
7
8
|
export function generateMinikubeInfra(manifest, options = {}) {
|
|
@@ -19,6 +20,7 @@ export function generateMinikubeInfra(manifest, options = {}) {
|
|
|
19
20
|
appManifest: options.appManifest,
|
|
20
21
|
});
|
|
21
22
|
const storageArtifacts = generateStorageArtifacts({ manifest, namespace });
|
|
23
|
+
const secretStoreArtifacts = generateSecretStoreArtifacts({ manifest, namespace });
|
|
22
24
|
const apiArtifacts = generateApiInfrastructureArtifacts({
|
|
23
25
|
data: options.appManifest?.data,
|
|
24
26
|
databaseProvider: manifest.database?.provider,
|
|
@@ -27,11 +29,13 @@ export function generateMinikubeInfra(manifest, options = {}) {
|
|
|
27
29
|
...authArtifacts.resources,
|
|
28
30
|
...authzArtifacts.resources,
|
|
29
31
|
...storageArtifacts.resources,
|
|
32
|
+
...secretStoreArtifacts.resources,
|
|
30
33
|
]);
|
|
31
34
|
const extraEnvEntries = unique([
|
|
32
35
|
...authArtifacts.envEntries,
|
|
33
36
|
...authzArtifacts.envEntries,
|
|
34
37
|
...storageArtifacts.envEntries,
|
|
38
|
+
...secretStoreArtifacts.envEntries,
|
|
35
39
|
]);
|
|
36
40
|
const baseFiles = generateMinikubeBaseArtifacts({
|
|
37
41
|
manifest,
|
|
@@ -44,6 +48,7 @@ export function generateMinikubeInfra(manifest, options = {}) {
|
|
|
44
48
|
...authArtifacts.warnings,
|
|
45
49
|
...authzArtifacts.warnings,
|
|
46
50
|
...storageArtifacts.warnings,
|
|
51
|
+
...secretStoreArtifacts.warnings,
|
|
47
52
|
...apiArtifacts.warnings,
|
|
48
53
|
]);
|
|
49
54
|
return {
|
|
@@ -52,6 +57,7 @@ export function generateMinikubeInfra(manifest, options = {}) {
|
|
|
52
57
|
...authArtifacts.files,
|
|
53
58
|
...authzArtifacts.files,
|
|
54
59
|
...storageArtifacts.files,
|
|
60
|
+
...secretStoreArtifacts.files,
|
|
55
61
|
...apiArtifacts.files,
|
|
56
62
|
],
|
|
57
63
|
warnings,
|
|
@@ -73,6 +79,8 @@ function collectProviders(manifest) {
|
|
|
73
79
|
providers.add(manifest.database.provider);
|
|
74
80
|
if (manifest.storage?.provider)
|
|
75
81
|
providers.add(manifest.storage.provider);
|
|
82
|
+
if (manifest.secretStore?.provider)
|
|
83
|
+
providers.add(manifest.secretStore.provider);
|
|
76
84
|
if (manifest.state?.provider)
|
|
77
85
|
providers.add(manifest.state.provider);
|
|
78
86
|
return [...providers].sort();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/minikube/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kCAAkC,EAAE,MAAM,oBAAoB,CAAC;AAOxE,OAAO,EAAE,6BAA6B,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,8BAA8B,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,EAAE,6BAA6B,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAErD,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAErC,MAAM,UAAU,qBAAqB,CACnC,QAA4B,EAC5B,UAA2C,EAAE;IAE7C,IAAI,QAAQ,CAAC,UAAU,EAAE,MAAM,KAAK,UAAU,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CACb,0EAA0E,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,WAAW,KAAK,CAC1H,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,EAAE,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CACb,wDAAwD,QAAQ,CAAC,QAAQ,CAAC,QAAQ,oCAAoC,CACvH,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEtD,MAAM,aAAa,GAAG,6BAA6B,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IAC7E,MAAM,cAAc,GAAG,8BAA8B,CAAC;QACpD,QAAQ;QACR,SAAS;QACT,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAG,wBAAwB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,kCAAkC,CAAC;QACtD,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,IAAI;QAC/B,gBAAgB,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ;KAC9C,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,MAAM,CAAC;QAC5B,GAAG,aAAa,CAAC,SAAS;QAC1B,GAAG,cAAc,CAAC,SAAS;QAC3B,GAAG,gBAAgB,CAAC,SAAS;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/minikube/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { generateApiInfrastructureArtifacts } from '../../apiArtifacts';\nimport type {\n GeneratedPackageDependency,\n InfraManifestInput,\n InfrastructureGenerationOptions,\n InfrastructureGenerationResult,\n} from '../../types';\nimport { generateAuthProviderArtifacts } from './auth';\nimport { generateAuthorizationArtifacts } from './authz';\nimport { generateMinikubeBaseArtifacts } from './base';\nimport { generateSecretStoreArtifacts } from './secrets';\nimport { generateStorageArtifacts } from './storage';\n\nconst DEFAULT_NAMESPACE = 'ankh-app';\n\nexport function generateMinikubeInfra(\n manifest: InfraManifestInput,\n options: InfrastructureGenerationOptions = {},\n): InfrastructureGenerationResult {\n if (manifest.deployment?.target !== 'minikube') {\n throw new Error(\n `Minikube adapter only supports deployment target \"minikube\" (received \"${manifest.deployment?.target ?? 'undefined'}\").`,\n );\n }\n\n if (manifest.database?.provider && manifest.database.provider !== 'supabase') {\n throw new Error(\n `Unsupported database provider for minikube adapter: \"${manifest.database.provider}\". Only \"supabase\" is implemented.`,\n );\n }\n\n const namespace = resolveNamespace(manifest, options);\n\n const authArtifacts = generateAuthProviderArtifacts({ manifest, namespace });\n const authzArtifacts = generateAuthorizationArtifacts({\n manifest,\n namespace,\n appManifest: options.appManifest,\n });\n const storageArtifacts = generateStorageArtifacts({ manifest, namespace });\n const secretStoreArtifacts = generateSecretStoreArtifacts({ manifest, namespace });\n const apiArtifacts = generateApiInfrastructureArtifacts({\n data: options.appManifest?.data,\n databaseProvider: manifest.database?.provider,\n });\n\n const extraResources = unique([\n ...authArtifacts.resources,\n ...authzArtifacts.resources,\n ...storageArtifacts.resources,\n ...secretStoreArtifacts.resources,\n ]);\n const extraEnvEntries = unique([\n ...authArtifacts.envEntries,\n ...authzArtifacts.envEntries,\n ...storageArtifacts.envEntries,\n ...secretStoreArtifacts.envEntries,\n ]);\n\n const baseFiles = generateMinikubeBaseArtifacts({\n manifest,\n namespace,\n extraResources,\n extraEnvEntries,\n });\n\n const warnings = unique([\n ...collectWarnings(manifest),\n ...authArtifacts.warnings,\n ...authzArtifacts.warnings,\n ...storageArtifacts.warnings,\n ...secretStoreArtifacts.warnings,\n ...apiArtifacts.warnings,\n ]);\n\n return {\n files: [\n ...baseFiles,\n ...authArtifacts.files,\n ...authzArtifacts.files,\n ...storageArtifacts.files,\n ...secretStoreArtifacts.files,\n ...apiArtifacts.files,\n ],\n warnings,\n meta: {\n target: 'minikube',\n providers: collectProviders(manifest),\n },\n dependencies: collectDependencies(manifest),\n };\n}\n\nfunction collectProviders(manifest: InfraManifestInput): string[] {\n const providers = new Set<string>();\n\n if (manifest.auth?.provider) providers.add(manifest.auth.provider);\n if (manifest.auth?.authorization?.engine) {\n providers.add(manifest.auth.authorization.engine);\n }\n if (manifest.database?.provider) providers.add(manifest.database.provider);\n if (manifest.storage?.provider) providers.add(manifest.storage.provider);\n if (manifest.secretStore?.provider) providers.add(manifest.secretStore.provider);\n if (manifest.state?.provider) providers.add(manifest.state.provider);\n\n return [...providers].sort();\n}\n\nfunction collectDependencies(manifest: InfraManifestInput): readonly GeneratedPackageDependency[] {\n if (manifest.state?.provider !== 'legend') {\n return [];\n }\n\n return [\n {\n name: '@ankhorage/state-legend',\n version: '^0.1.0',\n reason: 'Selected by infra.state.provider=legend.',\n },\n ];\n}\n\nfunction collectWarnings(manifest: InfraManifestInput): string[] {\n const warnings: string[] = [];\n\n if (manifest.deployment?.monitoring) {\n warnings.push(\n 'Monitoring is enabled in manifest, but monitoring stack resources are not generated yet.',\n );\n }\n\n if (manifest.networking?.cdn) {\n warnings.push('CDN is enabled in manifest, but CDN resources are not generated for minikube.');\n }\n\n return warnings;\n}\n\nfunction resolveNamespace(\n manifest: InfraManifestInput,\n options: InfrastructureGenerationOptions,\n): string {\n const source =\n manifest.networking?.domain?.trim() ?? options.namespaceHint?.trim() ?? DEFAULT_NAMESPACE;\n\n const normalized = source\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n\n const safe = normalized.slice(0, 63).replace(/-+$/g, '');\n return safe || DEFAULT_NAMESPACE;\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)];\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { InfraManifestInput } from '../../../types';
|
|
2
|
+
import { type MinikubeAdapterArtifacts } from '../contracts';
|
|
3
|
+
export declare function generateSecretStoreArtifacts(args: {
|
|
4
|
+
readonly manifest: InfraManifestInput;
|
|
5
|
+
readonly namespace: string;
|
|
6
|
+
}): MinikubeAdapterArtifacts;
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapters/minikube/secrets/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAA0B,KAAK,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAGrF,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IACjD,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,GAAG,wBAAwB,CAS3B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SUPABASE_VAULT_SECRET_STORE_PROVIDER } from '@ankhorage/supabase-vault';
|
|
2
|
+
import { emptyMinikubeArtifacts } from '../contracts';
|
|
3
|
+
import { generateSupabaseVaultSecretStoreArtifacts } from './supabase-vault';
|
|
4
|
+
export function generateSecretStoreArtifacts(args) {
|
|
5
|
+
const provider = args.manifest.secretStore?.provider;
|
|
6
|
+
if (!provider)
|
|
7
|
+
return emptyMinikubeArtifacts();
|
|
8
|
+
if (provider === SUPABASE_VAULT_SECRET_STORE_PROVIDER) {
|
|
9
|
+
return generateSupabaseVaultSecretStoreArtifacts(args);
|
|
10
|
+
}
|
|
11
|
+
throw new Error(`Unsupported secret-store provider for minikube adapter: "${provider}".`);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/adapters/minikube/secrets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oCAAoC,EAAE,MAAM,2BAA2B,CAAC;AAGjF,OAAO,EAAE,sBAAsB,EAAiC,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,yCAAyC,EAAE,MAAM,kBAAkB,CAAC;AAE7E,MAAM,UAAU,4BAA4B,CAAC,IAG5C;IACC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC;IACrD,IAAI,CAAC,QAAQ;QAAE,OAAO,sBAAsB,EAAE,CAAC;IAE/C,IAAI,QAAQ,KAAK,oCAAoC,EAAE,CAAC;QACtD,OAAO,yCAAyC,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,4DAA4D,QAAQ,IAAI,CAAC,CAAC;AAC5F,CAAC","sourcesContent":["import { SUPABASE_VAULT_SECRET_STORE_PROVIDER } from '@ankhorage/supabase-vault';\n\nimport type { InfraManifestInput } from '../../../types';\nimport { emptyMinikubeArtifacts, type MinikubeAdapterArtifacts } from '../contracts';\nimport { generateSupabaseVaultSecretStoreArtifacts } from './supabase-vault';\n\nexport function generateSecretStoreArtifacts(args: {\n readonly manifest: InfraManifestInput;\n readonly namespace: string;\n}): MinikubeAdapterArtifacts {\n const provider = args.manifest.secretStore?.provider;\n if (!provider) return emptyMinikubeArtifacts();\n\n if (provider === SUPABASE_VAULT_SECRET_STORE_PROVIDER) {\n return generateSupabaseVaultSecretStoreArtifacts(args);\n }\n\n throw new Error(`Unsupported secret-store provider for minikube adapter: \"${provider}\".`);\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { InfraManifestInput } from '../../../../types';
|
|
2
|
+
import type { MinikubeAdapterArtifacts } from '../../contracts';
|
|
3
|
+
export declare const SUPABASE_VAULT_MIGRATION_PATH = "infra/minikube/supabase/migrations/202607120001_ankhorage_supabase_vault.sql";
|
|
4
|
+
export declare function generateSupabaseVaultSecretStoreArtifacts(args: {
|
|
5
|
+
readonly manifest: InfraManifestInput;
|
|
6
|
+
readonly namespace: string;
|
|
7
|
+
}): MinikubeAdapterArtifacts;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/minikube/secrets/supabase-vault/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAEhE,eAAO,MAAM,6BAA6B,iFACsC,CAAC;AAEjF,wBAAgB,yCAAyC,CAAC,IAAI,EAAE;IAC9D,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,GAAG,wBAAwB,CAqB3B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { SUPABASE_VAULT_MIGRATION_SQL, SUPABASE_VAULT_SECRET_STORE_PROVIDER, } from '@ankhorage/supabase-vault';
|
|
2
|
+
export const SUPABASE_VAULT_MIGRATION_PATH = 'infra/minikube/supabase/migrations/202607120001_ankhorage_supabase_vault.sql';
|
|
3
|
+
export function generateSupabaseVaultSecretStoreArtifacts(args) {
|
|
4
|
+
validateOAuthSecretReferences(args.manifest);
|
|
5
|
+
return {
|
|
6
|
+
files: [
|
|
7
|
+
{
|
|
8
|
+
path: SUPABASE_VAULT_MIGRATION_PATH,
|
|
9
|
+
content: `${SUPABASE_VAULT_MIGRATION_SQL.trim()}\n`,
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
path: 'infra/minikube/secrets/supabase-vault.md',
|
|
13
|
+
content: getRuntimeGuide(args.namespace),
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
resources: [],
|
|
17
|
+
envEntries: [
|
|
18
|
+
`SECRET_STORE_PROVIDER=${SUPABASE_VAULT_SECRET_STORE_PROVIDER}`,
|
|
19
|
+
'SUPABASE_LOCAL_ENABLED=true',
|
|
20
|
+
],
|
|
21
|
+
warnings: [],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function validateOAuthSecretReferences(manifest) {
|
|
25
|
+
const oauth = manifest.auth?.oauth;
|
|
26
|
+
if (!oauth?.enabled)
|
|
27
|
+
return;
|
|
28
|
+
const enabledProviders = oauth.providers.filter((provider) => provider.enabled !== false);
|
|
29
|
+
if (enabledProviders.length === 0) {
|
|
30
|
+
throw new Error('OAuth is enabled but no OAuth provider is enabled.');
|
|
31
|
+
}
|
|
32
|
+
for (const provider of enabledProviders) {
|
|
33
|
+
if (!provider.credentialsRef?.trim()) {
|
|
34
|
+
throw new Error(`OAuth provider "${provider.id}" is enabled but does not define credentialsRef.`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function getRuntimeGuide(namespace) {
|
|
39
|
+
return `# Supabase Vault secret store
|
|
40
|
+
|
|
41
|
+
This project selects the provider-neutral secret-store backend through:
|
|
42
|
+
|
|
43
|
+
\`\`\`text
|
|
44
|
+
infra.secretStore.provider = ${SUPABASE_VAULT_SECRET_STORE_PROVIDER}
|
|
45
|
+
\`\`\`
|
|
46
|
+
|
|
47
|
+
The immutable migration at:
|
|
48
|
+
|
|
49
|
+
\`\`\`text
|
|
50
|
+
${SUPABASE_VAULT_MIGRATION_PATH}
|
|
51
|
+
\`\`\`
|
|
52
|
+
|
|
53
|
+
is applied by the existing local Supabase migration lifecycle during \`scripts/up.sh\`.
|
|
54
|
+
|
|
55
|
+
## Security boundary
|
|
56
|
+
|
|
57
|
+
- Secret values are stored only through Supabase Vault.
|
|
58
|
+
- Public manifests contain logical references such as \`auth/oauth/google\`, never values.
|
|
59
|
+
- Project and environment scope are supplied by trusted server code.
|
|
60
|
+
- The browser may receive secret metadata, but must never receive resolved values or Vault IDs.
|
|
61
|
+
- Bootstrap database access must come from trusted process environment or workload identity.
|
|
62
|
+
- Do not expose service-role keys, provider secrets, or resolved payloads through
|
|
63
|
+
\`NEXT_PUBLIC_*\`, \`EXPO_PUBLIC_*\`, generated YAML, tracked JSON, or app bundles.
|
|
64
|
+
|
|
65
|
+
## Trusted adapter composition
|
|
66
|
+
|
|
67
|
+
Use \`createInfraSecretStoreAdapter\` from \`@ankhorage/infra\` in server-only code and pass
|
|
68
|
+
a trusted Supabase Vault SQL client. The app manifest chooses the provider; privileged connection
|
|
69
|
+
configuration does not belong in the manifest.
|
|
70
|
+
|
|
71
|
+
Generated Kubernetes namespace: \`${namespace}\`.
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/adapters/minikube/secrets/supabase-vault/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,oCAAoC,GACrC,MAAM,2BAA2B,CAAC;AAKnC,MAAM,CAAC,MAAM,6BAA6B,GACxC,8EAA8E,CAAC;AAEjF,MAAM,UAAU,yCAAyC,CAAC,IAGzD;IACC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,6BAA6B;gBACnC,OAAO,EAAE,GAAG,4BAA4B,CAAC,IAAI,EAAE,IAAI;aACpD;YACD;gBACE,IAAI,EAAE,0CAA0C;gBAChD,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC;aACzC;SACF;QACD,SAAS,EAAE,EAAE;QACb,UAAU,EAAE;YACV,yBAAyB,oCAAoC,EAAE;YAC/D,6BAA6B;SAC9B;QACD,QAAQ,EAAE,EAAE;KACb,CAAC;AACJ,CAAC;AAED,SAAS,6BAA6B,CAAC,QAA4B;IACjE,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACnC,IAAI,CAAC,KAAK,EAAE,OAAO;QAAE,OAAO;IAE5B,MAAM,gBAAgB,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC;IAC1F,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CACb,mBAAmB,QAAQ,CAAC,EAAE,kDAAkD,CACjF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,SAAiB;IACxC,OAAO;;;;;+BAKsB,oCAAoC;;;;;;EAMjE,6BAA6B;;;;;;;;;;;;;;;;;;;;;oCAqBK,SAAS;CAC5C,CAAC;AACF,CAAC","sourcesContent":["import {\n SUPABASE_VAULT_MIGRATION_SQL,\n SUPABASE_VAULT_SECRET_STORE_PROVIDER,\n} from '@ankhorage/supabase-vault';\n\nimport type { InfraManifestInput } from '../../../../types';\nimport type { MinikubeAdapterArtifacts } from '../../contracts';\n\nexport const SUPABASE_VAULT_MIGRATION_PATH =\n 'infra/minikube/supabase/migrations/202607120001_ankhorage_supabase_vault.sql';\n\nexport function generateSupabaseVaultSecretStoreArtifacts(args: {\n readonly manifest: InfraManifestInput;\n readonly namespace: string;\n}): MinikubeAdapterArtifacts {\n validateOAuthSecretReferences(args.manifest);\n\n return {\n files: [\n {\n path: SUPABASE_VAULT_MIGRATION_PATH,\n content: `${SUPABASE_VAULT_MIGRATION_SQL.trim()}\\n`,\n },\n {\n path: 'infra/minikube/secrets/supabase-vault.md',\n content: getRuntimeGuide(args.namespace),\n },\n ],\n resources: [],\n envEntries: [\n `SECRET_STORE_PROVIDER=${SUPABASE_VAULT_SECRET_STORE_PROVIDER}`,\n 'SUPABASE_LOCAL_ENABLED=true',\n ],\n warnings: [],\n };\n}\n\nfunction validateOAuthSecretReferences(manifest: InfraManifestInput): void {\n const oauth = manifest.auth?.oauth;\n if (!oauth?.enabled) return;\n\n const enabledProviders = oauth.providers.filter((provider) => provider.enabled !== false);\n if (enabledProviders.length === 0) {\n throw new Error('OAuth is enabled but no OAuth provider is enabled.');\n }\n\n for (const provider of enabledProviders) {\n if (!provider.credentialsRef?.trim()) {\n throw new Error(\n `OAuth provider \"${provider.id}\" is enabled but does not define credentialsRef.`,\n );\n }\n }\n}\n\nfunction getRuntimeGuide(namespace: string): string {\n return `# Supabase Vault secret store\n\nThis project selects the provider-neutral secret-store backend through:\n\n\\`\\`\\`text\ninfra.secretStore.provider = ${SUPABASE_VAULT_SECRET_STORE_PROVIDER}\n\\`\\`\\`\n\nThe immutable migration at:\n\n\\`\\`\\`text\n${SUPABASE_VAULT_MIGRATION_PATH}\n\\`\\`\\`\n\nis applied by the existing local Supabase migration lifecycle during \\`scripts/up.sh\\`.\n\n## Security boundary\n\n- Secret values are stored only through Supabase Vault.\n- Public manifests contain logical references such as \\`auth/oauth/google\\`, never values.\n- Project and environment scope are supplied by trusted server code.\n- The browser may receive secret metadata, but must never receive resolved values or Vault IDs.\n- Bootstrap database access must come from trusted process environment or workload identity.\n- Do not expose service-role keys, provider secrets, or resolved payloads through\n \\`NEXT_PUBLIC_*\\`, \\`EXPO_PUBLIC_*\\`, generated YAML, tracked JSON, or app bundles.\n\n## Trusted adapter composition\n\nUse \\`createInfraSecretStoreAdapter\\` from \\`@ankhorage/infra\\` in server-only code and pass\na trusted Supabase Vault SQL client. The app manifest chooses the provider; privileged connection\nconfiguration does not belong in the manifest.\n\nGenerated Kubernetes namespace: \\`${namespace}\\`.\n`;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { InfraGenerationInput, InfraManifestInput, InfrastructureGenerationOptions, InfrastructureGenerationResult } from './types';
|
|
2
2
|
export type { ApiInfrastructureArtifacts } from './apiArtifacts';
|
|
3
3
|
export { generateApiInfrastructureArtifacts } from './apiArtifacts';
|
|
4
|
+
export { createInfraSecretStoreAdapter, type CreateInfraSecretStoreAdapterInput, type InfraSecretStoreProviders, } from './secretStore';
|
|
4
5
|
export type { GeneratedFile, GeneratedInfrastructureFile, GeneratedPackageDependency, InfraDiagnostic, InfraGenerationInput, InfraGenerationOptions, InfraGenerationResult, InfraManifestInput, InfrastructureGenerationMeta, InfrastructureGenerationOptions, InfrastructureGenerationResult, PackageDependency, } from './types';
|
|
5
6
|
export declare function generateInfra(input: InfraGenerationInput): InfrastructureGenerationResult;
|
|
6
7
|
export declare function generateInfrastructure(manifest: InfraManifestInput, options?: InfrastructureGenerationOptions): InfrastructureGenerationResult;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAClB,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,kCAAkC,EAAE,MAAM,gBAAgB,CAAC;AACpE,YAAY,EACV,aAAa,EACb,2BAA2B,EAC3B,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,4BAA4B,EAC5B,+BAA+B,EAC/B,8BAA8B,EAC9B,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB,wBAAgB,aAAa,CAAC,KAAK,EAAE,oBAAoB,GAAG,8BAA8B,CAEzF;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,+BAAoC,GAC5C,8BAA8B,CAUhC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAClB,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,kCAAkC,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EACL,6BAA6B,EAC7B,KAAK,kCAAkC,EACvC,KAAK,yBAAyB,GAC/B,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,aAAa,EACb,2BAA2B,EAC3B,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,4BAA4B,EAC5B,+BAA+B,EAC/B,8BAA8B,EAC9B,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB,wBAAgB,aAAa,CAAC,KAAK,EAAE,oBAAoB,GAAG,8BAA8B,CAEzF;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,+BAAoC,GAC5C,8BAA8B,CAUhC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { generateMinikubeInfra } from './adapters/minikube';
|
|
2
2
|
export { generateApiInfrastructureArtifacts } from './apiArtifacts';
|
|
3
|
+
export { createInfraSecretStoreAdapter, } from './secretStore';
|
|
3
4
|
export function generateInfra(input) {
|
|
4
5
|
return generateInfrastructure(input.manifest, input.options ?? {});
|
|
5
6
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAS5D,OAAO,EAAE,kCAAkC,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAS5D,OAAO,EAAE,kCAAkC,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EACL,6BAA6B,GAG9B,MAAM,eAAe,CAAC;AAgBvB,MAAM,UAAU,aAAa,CAAC,KAA2B;IACvD,OAAO,sBAAsB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,QAA4B,EAC5B,UAA2C,EAAE;IAE7C,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC","sourcesContent":["import { generateMinikubeInfra } from './adapters/minikube';\nimport type {\n InfraGenerationInput,\n InfraManifestInput,\n InfrastructureGenerationOptions,\n InfrastructureGenerationResult,\n} from './types';\n\nexport type { ApiInfrastructureArtifacts } from './apiArtifacts';\nexport { generateApiInfrastructureArtifacts } from './apiArtifacts';\nexport {\n createInfraSecretStoreAdapter,\n type CreateInfraSecretStoreAdapterInput,\n type InfraSecretStoreProviders,\n} from './secretStore';\nexport type {\n GeneratedFile,\n GeneratedInfrastructureFile,\n GeneratedPackageDependency,\n InfraDiagnostic,\n InfraGenerationInput,\n InfraGenerationOptions,\n InfraGenerationResult,\n InfraManifestInput,\n InfrastructureGenerationMeta,\n InfrastructureGenerationOptions,\n InfrastructureGenerationResult,\n PackageDependency,\n} from './types';\n\nexport function generateInfra(input: InfraGenerationInput): InfrastructureGenerationResult {\n return generateInfrastructure(input.manifest, input.options ?? {});\n}\n\nexport function generateInfrastructure(\n manifest: InfraManifestInput,\n options: InfrastructureGenerationOptions = {},\n): InfrastructureGenerationResult {\n if (!manifest.deployment) {\n throw new Error('Deployment configuration is missing.');\n }\n\n if (manifest.deployment.target !== 'minikube') {\n throw new Error(`Unsupported deployment target: ${manifest.deployment.target}`);\n }\n\n return generateMinikubeInfra(manifest, options);\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SecretStoreAdapter } from '@ankhorage/contracts/secrets';
|
|
2
|
+
import { type SupabaseVaultAdapterOptions } from '@ankhorage/supabase-vault';
|
|
3
|
+
import type { InfraManifestInput } from './types';
|
|
4
|
+
export interface InfraSecretStoreProviders {
|
|
5
|
+
readonly supabaseVault?: SupabaseVaultAdapterOptions;
|
|
6
|
+
}
|
|
7
|
+
export interface CreateInfraSecretStoreAdapterInput {
|
|
8
|
+
readonly manifest: Pick<InfraManifestInput, 'secretStore'>;
|
|
9
|
+
readonly providers: InfraSecretStoreProviders;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates the configured server-only secret-store adapter.
|
|
13
|
+
*
|
|
14
|
+
* Bootstrap credentials and trusted clients belong in `providers`; they must never be read from
|
|
15
|
+
* the public app manifest. A missing `infra.secretStore` returns `null` because apps without
|
|
16
|
+
* secret-backed features do not require a secret store.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createInfraSecretStoreAdapter(input: CreateInfraSecretStoreAdapterInput): SecretStoreAdapter | null;
|
|
19
|
+
//# sourceMappingURL=secretStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secretStore.d.ts","sourceRoot":"","sources":["../src/secretStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAGL,KAAK,2BAA2B,EACjC,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,aAAa,CAAC,EAAE,2BAA2B,CAAC;CACtD;AAED,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;IAC3D,QAAQ,CAAC,SAAS,EAAE,yBAAyB,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,kCAAkC,GACxC,kBAAkB,GAAG,IAAI,CAgB3B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createSupabaseVaultAdapter, SUPABASE_VAULT_SECRET_STORE_PROVIDER, } from '@ankhorage/supabase-vault';
|
|
2
|
+
/**
|
|
3
|
+
* Creates the configured server-only secret-store adapter.
|
|
4
|
+
*
|
|
5
|
+
* Bootstrap credentials and trusted clients belong in `providers`; they must never be read from
|
|
6
|
+
* the public app manifest. A missing `infra.secretStore` returns `null` because apps without
|
|
7
|
+
* secret-backed features do not require a secret store.
|
|
8
|
+
*/
|
|
9
|
+
export function createInfraSecretStoreAdapter(input) {
|
|
10
|
+
const provider = input.manifest.secretStore?.provider;
|
|
11
|
+
if (!provider)
|
|
12
|
+
return null;
|
|
13
|
+
if (provider === SUPABASE_VAULT_SECRET_STORE_PROVIDER) {
|
|
14
|
+
const options = input.providers.supabaseVault;
|
|
15
|
+
if (!options) {
|
|
16
|
+
throw new Error('Secret-store provider "supabase-vault" requires trusted Supabase Vault adapter options.');
|
|
17
|
+
}
|
|
18
|
+
return createSupabaseVaultAdapter(options);
|
|
19
|
+
}
|
|
20
|
+
throw new Error(`Unsupported secret-store provider: "${provider}".`);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=secretStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secretStore.js","sourceRoot":"","sources":["../src/secretStore.ts"],"names":[],"mappings":"AACA,OAAO,EACL,0BAA0B,EAC1B,oCAAoC,GAErC,MAAM,2BAA2B,CAAC;AAanC;;;;;;GAMG;AACH,MAAM,UAAU,6BAA6B,CAC3C,KAAyC;IAEzC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC;IACtD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,IAAI,QAAQ,KAAK,oCAAoC,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,aAAa,CAAC;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;QACJ,CAAC;QAED,OAAO,0BAA0B,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,IAAI,CAAC,CAAC;AACvE,CAAC","sourcesContent":["import type { SecretStoreAdapter } from '@ankhorage/contracts/secrets';\nimport {\n createSupabaseVaultAdapter,\n SUPABASE_VAULT_SECRET_STORE_PROVIDER,\n type SupabaseVaultAdapterOptions,\n} from '@ankhorage/supabase-vault';\n\nimport type { InfraManifestInput } from './types';\n\nexport interface InfraSecretStoreProviders {\n readonly supabaseVault?: SupabaseVaultAdapterOptions;\n}\n\nexport interface CreateInfraSecretStoreAdapterInput {\n readonly manifest: Pick<InfraManifestInput, 'secretStore'>;\n readonly providers: InfraSecretStoreProviders;\n}\n\n/**\n * Creates the configured server-only secret-store adapter.\n *\n * Bootstrap credentials and trusted clients belong in `providers`; they must never be read from\n * the public app manifest. A missing `infra.secretStore` returns `null` because apps without\n * secret-backed features do not require a secret store.\n */\nexport function createInfraSecretStoreAdapter(\n input: CreateInfraSecretStoreAdapterInput,\n): SecretStoreAdapter | null {\n const provider = input.manifest.secretStore?.provider;\n if (!provider) return null;\n\n if (provider === SUPABASE_VAULT_SECRET_STORE_PROVIDER) {\n const options = input.providers.supabaseVault;\n if (!options) {\n throw new Error(\n 'Secret-store provider \"supabase-vault\" requires trusted Supabase Vault adapter options.',\n );\n }\n\n return createSupabaseVaultAdapter(options);\n }\n\n throw new Error(`Unsupported secret-store provider: \"${provider}\".`);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/infra",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"description": "Project-aware infrastructure generation library and executable Ankh provider for Ankhorage.",
|
|
6
6
|
"homepage": "https://github.com/ankhorage/infra#readme",
|
|
7
7
|
"bugs": {
|
|
@@ -28,12 +28,15 @@
|
|
|
28
28
|
"react-native",
|
|
29
29
|
"supabase",
|
|
30
30
|
"postgres",
|
|
31
|
+
"vault",
|
|
32
|
+
"secret-store",
|
|
31
33
|
"kubernetes",
|
|
32
34
|
"minikube",
|
|
33
35
|
"openapi"
|
|
34
36
|
],
|
|
35
37
|
"dependencies": {
|
|
36
|
-
"@ankhorage/contracts": "^2.
|
|
38
|
+
"@ankhorage/contracts": "^2.1.0",
|
|
39
|
+
"@ankhorage/supabase-vault": "^0.2.0"
|
|
37
40
|
},
|
|
38
41
|
"files": [
|
|
39
42
|
"dist",
|
|
@@ -72,7 +75,8 @@
|
|
|
72
75
|
"infra.generate",
|
|
73
76
|
"infra.status",
|
|
74
77
|
"infra.up",
|
|
75
|
-
"infra.down"
|
|
78
|
+
"infra.down",
|
|
79
|
+
"infra.secret-store"
|
|
76
80
|
]
|
|
77
81
|
},
|
|
78
82
|
"publishConfig": {
|
|
@@ -46,12 +46,16 @@ export function generateMinikubeBaseArtifacts(args: {
|
|
|
46
46
|
const authProvider = manifest.auth?.provider ?? 'none';
|
|
47
47
|
const authzEngine = manifest.auth?.authorization?.engine ?? 'none';
|
|
48
48
|
const databaseProvider = manifest.database?.provider ?? 'none';
|
|
49
|
+
const secretStoreProvider = manifest.secretStore?.provider ?? 'none';
|
|
49
50
|
const storageMetadata = resolveAppInfraStorageMetadata(manifest);
|
|
50
51
|
const profileModel = resolveSupabaseProfileModel(manifest);
|
|
51
52
|
const monitoringEnabled = manifest.deployment?.monitoring === true;
|
|
52
53
|
const domain = manifest.networking?.domain ?? '';
|
|
53
54
|
const supabaseLocalEnabled =
|
|
54
|
-
authProvider === 'supabase' ||
|
|
55
|
+
authProvider === 'supabase' ||
|
|
56
|
+
databaseProvider === 'supabase' ||
|
|
57
|
+
storageMetadata !== null ||
|
|
58
|
+
secretStoreProvider === 'supabase-vault';
|
|
55
59
|
|
|
56
60
|
return [
|
|
57
61
|
{
|
|
@@ -90,6 +94,7 @@ export function generateMinikubeBaseArtifacts(args: {
|
|
|
90
94
|
authScope,
|
|
91
95
|
authProvider,
|
|
92
96
|
databaseProvider,
|
|
97
|
+
secretStoreProvider,
|
|
93
98
|
storageMetadata,
|
|
94
99
|
monitoringEnabled,
|
|
95
100
|
domain,
|
|
@@ -427,6 +432,7 @@ function getAppConfigMap(args: {
|
|
|
427
432
|
authScope: string;
|
|
428
433
|
authProvider: string;
|
|
429
434
|
databaseProvider: string;
|
|
435
|
+
secretStoreProvider: string;
|
|
430
436
|
storageMetadata: AppInfraStorageMetadata | null;
|
|
431
437
|
monitoringEnabled: boolean;
|
|
432
438
|
domain: string;
|
|
@@ -436,6 +442,7 @@ function getAppConfigMap(args: {
|
|
|
436
442
|
authScope,
|
|
437
443
|
authProvider,
|
|
438
444
|
databaseProvider,
|
|
445
|
+
secretStoreProvider,
|
|
439
446
|
storageMetadata,
|
|
440
447
|
monitoringEnabled,
|
|
441
448
|
domain,
|
|
@@ -459,6 +466,7 @@ data:
|
|
|
459
466
|
AUTH_SCOPE: "${authScope}"
|
|
460
467
|
AUTH_PROVIDER: "${authProvider}"
|
|
461
468
|
DATABASE_PROVIDER: "${databaseProvider}"
|
|
469
|
+
SECRET_STORE_PROVIDER: "${secretStoreProvider}"
|
|
462
470
|
${storageLines} NETWORK_DOMAIN: "${domain}"
|
|
463
471
|
`;
|
|
464
472
|
}
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
import { generateAuthProviderArtifacts } from './auth';
|
|
9
9
|
import { generateAuthorizationArtifacts } from './authz';
|
|
10
10
|
import { generateMinikubeBaseArtifacts } from './base';
|
|
11
|
+
import { generateSecretStoreArtifacts } from './secrets';
|
|
11
12
|
import { generateStorageArtifacts } from './storage';
|
|
12
13
|
|
|
13
14
|
const DEFAULT_NAMESPACE = 'ankh-app';
|
|
@@ -37,6 +38,7 @@ export function generateMinikubeInfra(
|
|
|
37
38
|
appManifest: options.appManifest,
|
|
38
39
|
});
|
|
39
40
|
const storageArtifacts = generateStorageArtifacts({ manifest, namespace });
|
|
41
|
+
const secretStoreArtifacts = generateSecretStoreArtifacts({ manifest, namespace });
|
|
40
42
|
const apiArtifacts = generateApiInfrastructureArtifacts({
|
|
41
43
|
data: options.appManifest?.data,
|
|
42
44
|
databaseProvider: manifest.database?.provider,
|
|
@@ -46,11 +48,13 @@ export function generateMinikubeInfra(
|
|
|
46
48
|
...authArtifacts.resources,
|
|
47
49
|
...authzArtifacts.resources,
|
|
48
50
|
...storageArtifacts.resources,
|
|
51
|
+
...secretStoreArtifacts.resources,
|
|
49
52
|
]);
|
|
50
53
|
const extraEnvEntries = unique([
|
|
51
54
|
...authArtifacts.envEntries,
|
|
52
55
|
...authzArtifacts.envEntries,
|
|
53
56
|
...storageArtifacts.envEntries,
|
|
57
|
+
...secretStoreArtifacts.envEntries,
|
|
54
58
|
]);
|
|
55
59
|
|
|
56
60
|
const baseFiles = generateMinikubeBaseArtifacts({
|
|
@@ -65,6 +69,7 @@ export function generateMinikubeInfra(
|
|
|
65
69
|
...authArtifacts.warnings,
|
|
66
70
|
...authzArtifacts.warnings,
|
|
67
71
|
...storageArtifacts.warnings,
|
|
72
|
+
...secretStoreArtifacts.warnings,
|
|
68
73
|
...apiArtifacts.warnings,
|
|
69
74
|
]);
|
|
70
75
|
|
|
@@ -74,6 +79,7 @@ export function generateMinikubeInfra(
|
|
|
74
79
|
...authArtifacts.files,
|
|
75
80
|
...authzArtifacts.files,
|
|
76
81
|
...storageArtifacts.files,
|
|
82
|
+
...secretStoreArtifacts.files,
|
|
77
83
|
...apiArtifacts.files,
|
|
78
84
|
],
|
|
79
85
|
warnings,
|
|
@@ -94,6 +100,7 @@ function collectProviders(manifest: InfraManifestInput): string[] {
|
|
|
94
100
|
}
|
|
95
101
|
if (manifest.database?.provider) providers.add(manifest.database.provider);
|
|
96
102
|
if (manifest.storage?.provider) providers.add(manifest.storage.provider);
|
|
103
|
+
if (manifest.secretStore?.provider) providers.add(manifest.secretStore.provider);
|
|
97
104
|
if (manifest.state?.provider) providers.add(manifest.state.provider);
|
|
98
105
|
|
|
99
106
|
return [...providers].sort();
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { SUPABASE_VAULT_MIGRATION_SQL } from '@ankhorage/supabase-vault';
|
|
2
|
+
import { describe, expect, test } from 'bun:test';
|
|
3
|
+
|
|
4
|
+
import { generateInfrastructure } from '../../../index';
|
|
5
|
+
import type { InfraManifestInput } from '../../../types';
|
|
6
|
+
import { SUPABASE_VAULT_MIGRATION_PATH } from './supabase-vault';
|
|
7
|
+
|
|
8
|
+
function createManifest(overrides: Partial<InfraManifestInput> = {}): InfraManifestInput {
|
|
9
|
+
return {
|
|
10
|
+
deployment: {
|
|
11
|
+
target: 'minikube',
|
|
12
|
+
monitoring: false,
|
|
13
|
+
},
|
|
14
|
+
secretStore: {
|
|
15
|
+
provider: 'supabase-vault',
|
|
16
|
+
},
|
|
17
|
+
plugins: [],
|
|
18
|
+
...overrides,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe('minikube secret-store generation', () => {
|
|
23
|
+
test('generates the released Supabase Vault migration through the existing lifecycle', () => {
|
|
24
|
+
const result = generateInfrastructure(createManifest());
|
|
25
|
+
const migration = result.files.find((file) => file.path === SUPABASE_VAULT_MIGRATION_PATH);
|
|
26
|
+
const envExample = result.files.find((file) => file.path === 'infra/minikube/.env.example');
|
|
27
|
+
const upScript = result.files.find((file) => file.path === 'infra/minikube/scripts/up.sh');
|
|
28
|
+
|
|
29
|
+
expect(migration?.content).toBe(`${SUPABASE_VAULT_MIGRATION_SQL.trim()}\n`);
|
|
30
|
+
expect(envExample?.content).toContain('SECRET_STORE_PROVIDER=supabase-vault');
|
|
31
|
+
expect(envExample?.content).toContain('SUPABASE_LOCAL_ENABLED=true');
|
|
32
|
+
expect(upScript?.content).toContain('SUPABASE_LOCAL_ENABLED="${SUPABASE_LOCAL_ENABLED:-true}"');
|
|
33
|
+
expect(result.meta.providers).toContain('supabase-vault');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('requires credentialsRef for every enabled OAuth provider', () => {
|
|
37
|
+
expect(() =>
|
|
38
|
+
generateInfrastructure(
|
|
39
|
+
createManifest({
|
|
40
|
+
auth: {
|
|
41
|
+
scope: 'global',
|
|
42
|
+
provider: 'supabase',
|
|
43
|
+
signIn: {
|
|
44
|
+
identifiers: ['email'],
|
|
45
|
+
},
|
|
46
|
+
oauth: {
|
|
47
|
+
enabled: true,
|
|
48
|
+
callbackRoute: '/auth/callback',
|
|
49
|
+
providers: [
|
|
50
|
+
{
|
|
51
|
+
id: 'google',
|
|
52
|
+
enabled: true,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
}),
|
|
58
|
+
),
|
|
59
|
+
).toThrow('does not define credentialsRef');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('accepts provider-neutral OAuth secret references without serializing values', () => {
|
|
63
|
+
const result = generateInfrastructure(
|
|
64
|
+
createManifest({
|
|
65
|
+
auth: {
|
|
66
|
+
scope: 'global',
|
|
67
|
+
provider: 'supabase',
|
|
68
|
+
signIn: {
|
|
69
|
+
identifiers: ['email'],
|
|
70
|
+
},
|
|
71
|
+
oauth: {
|
|
72
|
+
enabled: true,
|
|
73
|
+
callbackRoute: '/auth/callback',
|
|
74
|
+
providers: [
|
|
75
|
+
{
|
|
76
|
+
id: 'google',
|
|
77
|
+
enabled: true,
|
|
78
|
+
credentialsRef: 'auth/oauth/google',
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const serialized = JSON.stringify(result.files);
|
|
87
|
+
expect(serialized).toContain('auth/oauth/google');
|
|
88
|
+
expect(serialized).not.toContain('clientSecret');
|
|
89
|
+
expect(serialized).not.toContain('privateKey');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('rejects unknown secret-store providers', () => {
|
|
93
|
+
expect(() =>
|
|
94
|
+
generateInfrastructure(
|
|
95
|
+
createManifest({
|
|
96
|
+
secretStore: {
|
|
97
|
+
provider: 'aws-secrets-manager',
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
100
|
+
),
|
|
101
|
+
).toThrow('Unsupported secret-store provider for minikube adapter');
|
|
102
|
+
});
|
|
103
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SUPABASE_VAULT_SECRET_STORE_PROVIDER } from '@ankhorage/supabase-vault';
|
|
2
|
+
|
|
3
|
+
import type { InfraManifestInput } from '../../../types';
|
|
4
|
+
import { emptyMinikubeArtifacts, type MinikubeAdapterArtifacts } from '../contracts';
|
|
5
|
+
import { generateSupabaseVaultSecretStoreArtifacts } from './supabase-vault';
|
|
6
|
+
|
|
7
|
+
export function generateSecretStoreArtifacts(args: {
|
|
8
|
+
readonly manifest: InfraManifestInput;
|
|
9
|
+
readonly namespace: string;
|
|
10
|
+
}): MinikubeAdapterArtifacts {
|
|
11
|
+
const provider = args.manifest.secretStore?.provider;
|
|
12
|
+
if (!provider) return emptyMinikubeArtifacts();
|
|
13
|
+
|
|
14
|
+
if (provider === SUPABASE_VAULT_SECRET_STORE_PROVIDER) {
|
|
15
|
+
return generateSupabaseVaultSecretStoreArtifacts(args);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
throw new Error(`Unsupported secret-store provider for minikube adapter: "${provider}".`);
|
|
19
|
+
}
|