@ankhorage/infra 0.4.2 → 1.0.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 (45) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/dist/adapters/minikube/auth/supabase/index.d.ts.map +1 -1
  4. package/dist/adapters/minikube/auth/supabase/index.js +9 -39
  5. package/dist/adapters/minikube/auth/supabase/index.js.map +1 -1
  6. package/dist/adapters/minikube/auth/supabase/profile.d.ts +0 -1
  7. package/dist/adapters/minikube/auth/supabase/profile.d.ts.map +1 -1
  8. package/dist/adapters/minikube/auth/supabase/profile.js +1 -1
  9. package/dist/adapters/minikube/auth/supabase/profile.js.map +1 -1
  10. package/dist/adapters/minikube/authz/cerbos/index.d.ts.map +1 -1
  11. package/dist/adapters/minikube/authz/cerbos/index.js +22 -2
  12. package/dist/adapters/minikube/authz/cerbos/index.js.map +1 -1
  13. package/dist/adapters/minikube/base/index.d.ts +5 -2
  14. package/dist/adapters/minikube/base/index.d.ts.map +1 -1
  15. package/dist/adapters/minikube/base/index.js +2728 -1843
  16. package/dist/adapters/minikube/base/index.js.map +1 -1
  17. package/dist/adapters/minikube/contracts.d.ts +25 -0
  18. package/dist/adapters/minikube/contracts.d.ts.map +1 -1
  19. package/dist/adapters/minikube/contracts.js +1 -0
  20. package/dist/adapters/minikube/contracts.js.map +1 -1
  21. package/dist/adapters/minikube/index.d.ts.map +1 -1
  22. package/dist/adapters/minikube/index.js +18 -33
  23. package/dist/adapters/minikube/index.js.map +1 -1
  24. package/dist/adapters/minikube/secrets/supabase-vault/index.d.ts.map +1 -1
  25. package/dist/adapters/minikube/secrets/supabase-vault/index.js +49 -6
  26. package/dist/adapters/minikube/secrets/supabase-vault/index.js.map +1 -1
  27. package/dist/adapters/minikube/storage/supabase/index.d.ts.map +1 -1
  28. package/dist/adapters/minikube/storage/supabase/index.js +2 -1
  29. package/dist/adapters/minikube/storage/supabase/index.js.map +1 -1
  30. package/package.json +4 -1
  31. package/src/adapters/minikube/README.md +41 -38
  32. package/src/adapters/minikube/auth/supabase/index.ts +9 -40
  33. package/src/adapters/minikube/auth/supabase/profile.ts +1 -1
  34. package/src/adapters/minikube/authz/cerbos/index.ts +25 -3
  35. package/src/adapters/minikube/base/index.test.ts +380 -675
  36. package/src/adapters/minikube/base/index.ts +2935 -1878
  37. package/src/adapters/minikube/base/twoAppIsolation.integration.test.ts +636 -0
  38. package/src/adapters/minikube/contracts.ts +29 -0
  39. package/src/adapters/minikube/index.ts +18 -44
  40. package/src/adapters/minikube/secrets/index.test.ts +15 -7
  41. package/src/adapters/minikube/secrets/supabase-vault/index.ts +53 -6
  42. package/src/adapters/minikube/storage/supabase/index.ts +1 -5
  43. package/src/apis.test.ts +2 -1
  44. package/src/index.test.ts +63 -577
  45. package/src/minikubeImageLifecycle.test.ts +4 -3
@@ -1,9 +1,34 @@
1
1
  import type { GeneratedInfrastructureFile } from '../../types';
2
+ interface MinikubeProviderEndpoint {
3
+ name: string;
4
+ url: string;
5
+ }
6
+ interface MinikubeProviderReadinessCheck {
7
+ label: string;
8
+ namespace: string;
9
+ resource: string;
10
+ timeoutSeconds: number;
11
+ }
12
+ interface MinikubeProviderLifecycleCommand {
13
+ label: string;
14
+ command: string;
15
+ }
16
+ export interface MinikubeProviderLifecycle {
17
+ id: string;
18
+ namespace: string;
19
+ endpoints: MinikubeProviderEndpoint[];
20
+ readinessChecks: MinikubeProviderReadinessCheck[];
21
+ migrationCommands: MinikubeProviderLifecycleCommand[];
22
+ reconciliationCommands: MinikubeProviderLifecycleCommand[];
23
+ statusChecks: MinikubeProviderLifecycleCommand[];
24
+ }
2
25
  export interface MinikubeAdapterArtifacts {
3
26
  files: GeneratedInfrastructureFile[];
4
27
  resources: string[];
28
+ providerLifecycle: MinikubeProviderLifecycle[];
5
29
  envEntries: string[];
6
30
  warnings: string[];
7
31
  }
8
32
  export declare function emptyMinikubeArtifacts(): MinikubeAdapterArtifacts;
33
+ export {};
9
34
  //# sourceMappingURL=contracts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../../src/adapters/minikube/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,2BAA2B,EAAE,CAAC;IACrC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,sBAAsB,IAAI,wBAAwB,CAOjE"}
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../../src/adapters/minikube/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAE/D,UAAU,wBAAwB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,UAAU,8BAA8B;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,gCAAgC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,wBAAwB,EAAE,CAAC;IACtC,eAAe,EAAE,8BAA8B,EAAE,CAAC;IAClD,iBAAiB,EAAE,gCAAgC,EAAE,CAAC;IACtD,sBAAsB,EAAE,gCAAgC,EAAE,CAAC;IAC3D,YAAY,EAAE,gCAAgC,EAAE,CAAC;CAClD;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,2BAA2B,EAAE,CAAC;IACrC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iBAAiB,EAAE,yBAAyB,EAAE,CAAC;IAC/C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,sBAAsB,IAAI,wBAAwB,CAQjE"}
@@ -2,6 +2,7 @@ export function emptyMinikubeArtifacts() {
2
2
  return {
3
3
  files: [],
4
4
  resources: [],
5
+ providerLifecycle: [],
5
6
  envEntries: [],
6
7
  warnings: [],
7
8
  };
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../src/adapters/minikube/contracts.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,EAAE;QACb,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,EAAE;KACb,CAAC;AACJ,CAAC","sourcesContent":["import type { GeneratedInfrastructureFile } from '../../types';\n\nexport interface MinikubeAdapterArtifacts {\n files: GeneratedInfrastructureFile[];\n resources: string[];\n envEntries: string[];\n warnings: string[];\n}\n\nexport function emptyMinikubeArtifacts(): MinikubeAdapterArtifacts {\n return {\n files: [],\n resources: [],\n envEntries: [],\n warnings: [],\n };\n}\n"]}
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../src/adapters/minikube/contracts.ts"],"names":[],"mappings":"AAqCA,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,EAAE;QACb,iBAAiB,EAAE,EAAE;QACrB,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,EAAE;KACb,CAAC;AACJ,CAAC","sourcesContent":["import type { GeneratedInfrastructureFile } from '../../types';\n\ninterface MinikubeProviderEndpoint {\n name: string;\n url: string;\n}\n\ninterface MinikubeProviderReadinessCheck {\n label: string;\n namespace: string;\n resource: string;\n timeoutSeconds: number;\n}\n\ninterface MinikubeProviderLifecycleCommand {\n label: string;\n command: string;\n}\n\nexport interface MinikubeProviderLifecycle {\n id: string;\n namespace: string;\n endpoints: MinikubeProviderEndpoint[];\n readinessChecks: MinikubeProviderReadinessCheck[];\n migrationCommands: MinikubeProviderLifecycleCommand[];\n reconciliationCommands: MinikubeProviderLifecycleCommand[];\n statusChecks: MinikubeProviderLifecycleCommand[];\n}\n\nexport interface MinikubeAdapterArtifacts {\n files: GeneratedInfrastructureFile[];\n resources: string[];\n providerLifecycle: MinikubeProviderLifecycle[];\n envEntries: string[];\n warnings: string[];\n}\n\nexport function emptyMinikubeArtifacts(): MinikubeAdapterArtifacts {\n return {\n files: [],\n resources: [],\n providerLifecycle: [],\n envEntries: [],\n warnings: [],\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/minikube/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,kBAAkB,EAClB,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,aAAa,CAAC;AAUrB,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,+BAAoC,GAC5C,8BAA8B,CA6EhC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/minikube/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,kBAAkB,EAClB,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,aAAa,CAAC;AASrB,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,+BAAoC,GAC5C,8BAA8B,CAqFhC"}
@@ -1,10 +1,9 @@
1
1
  import { generateApiInfrastructureArtifacts } from '../../apiArtifacts';
2
2
  import { generateAuthProviderArtifacts } from './auth';
3
3
  import { generateAuthorizationArtifacts } from './authz';
4
- import { generateMinikubeBaseArtifacts } from './base';
4
+ import { APP_NAMESPACE, generateMinikubeBaseArtifacts } from './base';
5
5
  import { generateSecretStoreArtifacts } from './secrets';
6
6
  import { generateStorageArtifacts } from './storage';
7
- const DEFAULT_NAMESPACE = 'ankh-app';
8
7
  const CANONICAL_PROJECT_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$/;
9
8
  export function generateMinikubeInfra(manifest, options = {}) {
10
9
  if (manifest.deployment?.target !== 'minikube') {
@@ -13,10 +12,8 @@ export function generateMinikubeInfra(manifest, options = {}) {
13
12
  if (manifest.database?.provider && manifest.database.provider !== 'supabase') {
14
13
  throw new Error(`Unsupported database provider for minikube adapter: "${manifest.database.provider}". Only "supabase" is implemented.`);
15
14
  }
16
- const namespace = resolveNamespace(manifest, options);
17
- const supabaseProjectId = isSupabaseLocalEnabled(manifest)
18
- ? validateCanonicalProjectSlug(options.appManifest?.metadata.slug)
19
- : null;
15
+ const appSlug = validateCanonicalAppSlug(options.appManifest?.metadata.slug);
16
+ const namespace = APP_NAMESPACE;
20
17
  const authArtifacts = generateAuthProviderArtifacts({ manifest, namespace });
21
18
  const authzArtifacts = generateAuthorizationArtifacts({
22
19
  manifest,
@@ -35,6 +32,15 @@ export function generateMinikubeInfra(manifest, options = {}) {
35
32
  ...storageArtifacts.resources,
36
33
  ...secretStoreArtifacts.resources,
37
34
  ]);
35
+ const providerLifecycle = [
36
+ ...authArtifacts.providerLifecycle,
37
+ ...authzArtifacts.providerLifecycle,
38
+ ...storageArtifacts.providerLifecycle,
39
+ ...secretStoreArtifacts.providerLifecycle,
40
+ ];
41
+ const providerNamespaces = unique([
42
+ ...providerLifecycle.map((contribution) => contribution.namespace),
43
+ ]);
38
44
  const extraEnvEntries = unique([
39
45
  ...authArtifacts.envEntries,
40
46
  ...authzArtifacts.envEntries,
@@ -43,9 +49,10 @@ export function generateMinikubeInfra(manifest, options = {}) {
43
49
  ]);
44
50
  const baseFiles = generateMinikubeBaseArtifacts({
45
51
  manifest,
46
- namespace,
47
- supabaseProjectId,
52
+ appSlug,
48
53
  extraResources,
54
+ providerNamespaces,
55
+ providerLifecycle,
49
56
  extraEnvEntries,
50
57
  });
51
58
  const warnings = unique([
@@ -112,37 +119,15 @@ function collectWarnings(manifest) {
112
119
  }
113
120
  return warnings;
114
121
  }
115
- function isSupabaseLocalEnabled(manifest) {
116
- const authProvider = manifest.auth?.provider;
117
- const databaseProvider = manifest.database?.provider;
118
- const storageProvider = manifest.storage?.provider;
119
- const secretStoreProvider = manifest.secretStore?.provider;
120
- return (authProvider === 'supabase' ||
121
- databaseProvider === 'supabase' ||
122
- storageProvider === 'supabase' ||
123
- (storageProvider === 'auto' &&
124
- (authProvider === 'supabase' || databaseProvider === 'supabase')) ||
125
- secretStoreProvider === 'supabase-vault');
126
- }
127
- function validateCanonicalProjectSlug(slug) {
122
+ function validateCanonicalAppSlug(slug) {
128
123
  if (!slug) {
129
- throw new Error('Cannot generate local Supabase infrastructure: appManifest.metadata.slug is required.');
124
+ throw new Error('Cannot generate Minikube infrastructure: appManifest.metadata.slug is required.');
130
125
  }
131
126
  if (slug.trim() !== slug || !CANONICAL_PROJECT_SLUG_RE.test(slug)) {
132
- throw new Error('Cannot generate local Supabase infrastructure: appManifest.metadata.slug must be a canonical lowercase slug up to 40 characters using only a-z, 0-9, and hyphens, without leading or trailing hyphens.');
127
+ throw new Error('Cannot generate Minikube infrastructure: appManifest.metadata.slug must be a canonical lowercase slug up to 40 characters using only a-z, 0-9, and hyphens, without leading or trailing hyphens.');
133
128
  }
134
129
  return slug;
135
130
  }
136
- function resolveNamespace(manifest, options) {
137
- const source = manifest.networking?.domain?.trim() ?? options.namespaceHint?.trim() ?? DEFAULT_NAMESPACE;
138
- const normalized = source
139
- .toLowerCase()
140
- .replace(/[^a-z0-9-]/g, '-')
141
- .replace(/-+/g, '-')
142
- .replace(/^-|-$/g, '');
143
- const safe = normalized.slice(0, 63).replace(/-+$/g, '');
144
- return safe || DEFAULT_NAMESPACE;
145
- }
146
131
  function unique(values) {
147
132
  return [...new Set(values)];
148
133
  }
@@ -1 +1 @@
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';\nconst CANONICAL_PROJECT_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$/;\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 const supabaseProjectId = isSupabaseLocalEnabled(manifest)\n ? validateCanonicalProjectSlug(options.appManifest?.metadata.slug)\n : null;\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 supabaseProjectId,\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 isSupabaseLocalEnabled(manifest: InfraManifestInput): boolean {\n const authProvider = manifest.auth?.provider;\n const databaseProvider = manifest.database?.provider;\n const storageProvider = manifest.storage?.provider;\n const secretStoreProvider = manifest.secretStore?.provider;\n\n return (\n authProvider === 'supabase' ||\n databaseProvider === 'supabase' ||\n storageProvider === 'supabase' ||\n (storageProvider === 'auto' &&\n (authProvider === 'supabase' || databaseProvider === 'supabase')) ||\n secretStoreProvider === 'supabase-vault'\n );\n}\n\nfunction validateCanonicalProjectSlug(slug: string | undefined): string {\n if (!slug) {\n throw new Error(\n 'Cannot generate local Supabase infrastructure: appManifest.metadata.slug is required.',\n );\n }\n\n if (slug.trim() !== slug || !CANONICAL_PROJECT_SLUG_RE.test(slug)) {\n throw new Error(\n 'Cannot generate local Supabase infrastructure: appManifest.metadata.slug must be a canonical lowercase slug up to 40 characters using only a-z, 0-9, and hyphens, without leading or trailing hyphens.',\n );\n }\n\n return slug;\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"]}
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 { APP_NAMESPACE, generateMinikubeBaseArtifacts } from './base';\nimport { generateSecretStoreArtifacts } from './secrets';\nimport { generateStorageArtifacts } from './storage';\n\nconst CANONICAL_PROJECT_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$/;\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 appSlug = validateCanonicalAppSlug(options.appManifest?.metadata.slug);\n const namespace = APP_NAMESPACE;\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 providerLifecycle = [\n ...authArtifacts.providerLifecycle,\n ...authzArtifacts.providerLifecycle,\n ...storageArtifacts.providerLifecycle,\n ...secretStoreArtifacts.providerLifecycle,\n ];\n const providerNamespaces = unique([\n ...providerLifecycle.map((contribution) => contribution.namespace),\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 appSlug,\n extraResources,\n providerNamespaces,\n providerLifecycle,\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 validateCanonicalAppSlug(slug: string | undefined): string {\n if (!slug) {\n throw new Error(\n 'Cannot generate Minikube infrastructure: appManifest.metadata.slug is required.',\n );\n }\n\n if (slug.trim() !== slug || !CANONICAL_PROJECT_SLUG_RE.test(slug)) {\n throw new Error(\n 'Cannot generate Minikube infrastructure: appManifest.metadata.slug must be a canonical lowercase slug up to 40 characters using only a-z, 0-9, and hyphens, without leading or trailing hyphens.',\n );\n }\n\n return slug;\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)];\n}\n"]}
@@ -1 +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"}
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,CAmB3B"}
@@ -6,7 +6,7 @@ export function generateSupabaseVaultSecretStoreArtifacts(args) {
6
6
  files: [
7
7
  {
8
8
  path: SUPABASE_VAULT_MIGRATION_PATH,
9
- content: `${SUPABASE_VAULT_MIGRATION_SQL.trim()}\n`,
9
+ content: getCurrentSupabaseVaultMigrationSql(),
10
10
  },
11
11
  {
12
12
  path: 'infra/minikube/secrets/supabase-vault.md',
@@ -14,13 +14,55 @@ export function generateSupabaseVaultSecretStoreArtifacts(args) {
14
14
  },
15
15
  ],
16
16
  resources: [],
17
- envEntries: [
18
- `SECRET_STORE_PROVIDER=${SUPABASE_VAULT_SECRET_STORE_PROVIDER}`,
19
- 'SUPABASE_LOCAL_ENABLED=true',
20
- ],
17
+ providerLifecycle: [],
18
+ envEntries: [`SECRET_STORE_PROVIDER=${SUPABASE_VAULT_SECRET_STORE_PROVIDER}`],
21
19
  warnings: [],
22
20
  };
23
21
  }
22
+ function getCurrentSupabaseVaultMigrationSql() {
23
+ return `${SUPABASE_VAULT_MIGRATION_SQL.trim()
24
+ .replace('create extension if not exists supabase_vault with schema extensions;', () => `create schema if not exists vault;
25
+ do $$
26
+ begin
27
+ create extension if not exists supabase_vault with schema vault;
28
+ exception
29
+ when insufficient_privilege then
30
+ create table if not exists vault.secrets (
31
+ id uuid primary key default gen_random_uuid(),
32
+ secret text not null,
33
+ name text,
34
+ description text,
35
+ created_at timestamptz not null default now()
36
+ );
37
+
38
+ create or replace function vault.create_secret(
39
+ secret text,
40
+ name text default null,
41
+ description text default null
42
+ )
43
+ returns uuid
44
+ language plpgsql
45
+ security definer
46
+ set search_path = vault, public
47
+ as $vault$
48
+ declare
49
+ secret_id uuid;
50
+ begin
51
+ insert into vault.secrets (secret, name, description)
52
+ values (secret, name, description)
53
+ returning id into secret_id;
54
+
55
+ return secret_id;
56
+ end;
57
+ $vault$;
58
+
59
+ create or replace view vault.decrypted_secrets as
60
+ select id, secret as decrypted_secret
61
+ from vault.secrets;
62
+ end
63
+ $$;`)
64
+ .trim()}\n`;
65
+ }
24
66
  function validateOAuthSecretReferences(manifest) {
25
67
  const oauth = manifest.auth?.oauth;
26
68
  if (!oauth?.enabled)
@@ -50,7 +92,8 @@ The immutable migration at:
50
92
  ${SUPABASE_VAULT_MIGRATION_PATH}
51
93
  \`\`\`
52
94
 
53
- is applied by the existing local Supabase migration lifecycle during \`scripts/up.sh\`.
95
+ is applied by the Kubernetes-owned Supabase migration lifecycle during \`scripts/up.sh\`
96
+ with \`supabase migration up --db-url "$SUPABASE_DB_URL"\`.
54
97
 
55
98
  ## Security boundary
56
99
 
@@ -1 +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"]}
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,mCAAmC,EAAE;aAC/C;YACD;gBACE,IAAI,EAAE,0CAA0C;gBAChD,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC;aACzC;SACF;QACD,SAAS,EAAE,EAAE;QACb,iBAAiB,EAAE,EAAE;QACrB,UAAU,EAAE,CAAC,yBAAyB,oCAAoC,EAAE,CAAC;QAC7E,QAAQ,EAAE,EAAE;KACb,CAAC;AACJ,CAAC;AAED,SAAS,mCAAmC;IAC1C,OAAO,GAAG,4BAA4B,CAAC,IAAI,EAAE;SAC1C,OAAO,CACN,uEAAuE,EACvE,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAuCR,CACC;SACA,IAAI,EAAE,IAAI,CAAC;AAChB,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;;;;;;;;;;;;;;;;;;;;;;oCAsBK,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: getCurrentSupabaseVaultMigrationSql(),\n },\n {\n path: 'infra/minikube/secrets/supabase-vault.md',\n content: getRuntimeGuide(args.namespace),\n },\n ],\n resources: [],\n providerLifecycle: [],\n envEntries: [`SECRET_STORE_PROVIDER=${SUPABASE_VAULT_SECRET_STORE_PROVIDER}`],\n warnings: [],\n };\n}\n\nfunction getCurrentSupabaseVaultMigrationSql(): string {\n return `${SUPABASE_VAULT_MIGRATION_SQL.trim()\n .replace(\n 'create extension if not exists supabase_vault with schema extensions;',\n () => `create schema if not exists vault;\ndo $$\nbegin\n create extension if not exists supabase_vault with schema vault;\nexception\n when insufficient_privilege then\n create table if not exists vault.secrets (\n id uuid primary key default gen_random_uuid(),\n secret text not null,\n name text,\n description text,\n created_at timestamptz not null default now()\n );\n\n create or replace function vault.create_secret(\n secret text,\n name text default null,\n description text default null\n )\n returns uuid\n language plpgsql\n security definer\n set search_path = vault, public\n as $vault$\n declare\n secret_id uuid;\n begin\n insert into vault.secrets (secret, name, description)\n values (secret, name, description)\n returning id into secret_id;\n\n return secret_id;\n end;\n $vault$;\n\n create or replace view vault.decrypted_secrets as\n select id, secret as decrypted_secret\n from vault.secrets;\nend\n$$;`,\n )\n .trim()}\\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 Kubernetes-owned Supabase migration lifecycle during \\`scripts/up.sh\\`\nwith \\`supabase migration up --db-url \"$SUPABASE_DB_URL\"\\`.\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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/minikube/storage/supabase/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAEhE,wBAAgB,gCAAgC,CAAC,IAAI,EAAE;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mCAAmC,EAAE,OAAO,CAAC;CAC9C,GAAG,wBAAwB,CA2D3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/minikube/storage/supabase/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAEhE,wBAAgB,gCAAgC,CAAC,IAAI,EAAE;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mCAAmC,EAAE,OAAO,CAAC;CAC9C,GAAG,wBAAwB,CAuD3B"}
@@ -14,7 +14,7 @@ export function generateSupabaseStorageArtifacts(args) {
14
14
  `EXPO_PUBLIC_STORAGE_DEFAULT_BUCKET=${defaultBucket}`,
15
15
  ];
16
16
  if (includeSupabaseConnectionEnvEntries) {
17
- envEntries.push('', '# Supabase provider connection details', 'SUPABASE_SECRET_SYNC_ENABLED=true', 'SUPABASE_URL=', 'SUPABASE_ANON_KEY=', 'SUPABASE_SERVICE_ROLE_KEY=', 'SUPABASE_JWT_SECRET=', 'EXPO_PUBLIC_SUPABASE_URL=', 'EXPO_PUBLIC_SUPABASE_ANON_KEY=');
17
+ envEntries.push('', '# Supabase provider connection details', 'EXPO_PUBLIC_SUPABASE_URL=', 'EXPO_PUBLIC_SUPABASE_ANON_KEY=');
18
18
  }
19
19
  return {
20
20
  files: [
@@ -39,6 +39,7 @@ export function generateSupabaseStorageArtifacts(args) {
39
39
  `${resourceRoot}/supabase-storage.configmap.yaml`,
40
40
  `${resourceRoot}/app-runtime-storage.env.configmap.yaml`,
41
41
  ],
42
+ providerLifecycle: [],
42
43
  envEntries,
43
44
  warnings: [
44
45
  `Storage buckets are configured but not created automatically yet. Ensure buckets exist in Supabase Storage: ${bucketsCsv}.`,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/adapters/minikube/storage/supabase/index.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gCAAgC,CAAC,IAIhD;IACC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,mCAAmC,EAAE,GAAG,IAAI,CAAC;IACzE,MAAM,IAAI,GAAG,qCAAqC,CAAC;IACnD,MAAM,YAAY,GAAG,kBAAkB,CAAC;IACxC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvC,MAAM,UAAU,GAAG;QACjB,2BAA2B;QAC3B,4BAA4B;QAC5B,mBAAmB,UAAU,EAAE;QAC/B,0BAA0B,aAAa,EAAE;QACzC,uCAAuC;QACvC,+BAA+B,UAAU,EAAE;QAC3C,sCAAsC,aAAa,EAAE;KACtD,CAAC;IAEF,IAAI,mCAAmC,EAAE,CAAC;QACxC,UAAU,CAAC,IAAI,CACb,EAAE,EACF,wCAAwC,EACxC,mCAAmC,EACnC,eAAe,EACf,oBAAoB,EACpB,4BAA4B,EAC5B,sBAAsB,EACtB,2BAA2B,EAC3B,gCAAgC,CACjC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,GAAG,IAAI,kCAAkC;gBAC/C,OAAO,EAAE,2BAA2B,CAAC;oBACnC,SAAS;oBACT,UAAU;oBACV,aAAa;iBACd,CAAC;aACH;YACD;gBACE,IAAI,EAAE,GAAG,IAAI,yCAAyC;gBACtD,OAAO,EAAE,6BAA6B,CAAC;oBACrC,SAAS;oBACT,UAAU;oBACV,aAAa;iBACd,CAAC;aACH;SACF;QACD,SAAS,EAAE;YACT,GAAG,YAAY,kCAAkC;YACjD,GAAG,YAAY,yCAAyC;SACzD;QACD,UAAU;QACV,QAAQ,EAAE;YACR,+GAA+G,UAAU,GAAG;SAC7H;KACF,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAAC,IAIpC;IACC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAEtD,OAAO;;;;eAIM,SAAS;;;sBAGF,sBAAsB,CAAC,UAAU,CAAC;6BAC3B,sBAAsB,CAAC,aAAa,CAAC;CACjE,CAAC;AACF,CAAC;AAED,SAAS,6BAA6B,CAAC,IAItC;IACC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAEtD,OAAO;;;;eAIM,SAAS;;;;sBAIF,sBAAsB,CAAC,UAAU,CAAC;6BAC3B,sBAAsB,CAAC,aAAa,CAAC;;kCAEhC,sBAAsB,CAAC,UAAU,CAAC;yCAC3B,sBAAsB,CAAC,aAAa,CAAC;CAC7E,CAAC;AACF,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAa;IAC3C,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAC/D,CAAC","sourcesContent":["import type { MinikubeAdapterArtifacts } from '../../contracts';\n\nexport function generateSupabaseStorageArtifacts(args: {\n namespace: string;\n buckets: string[];\n includeSupabaseConnectionEnvEntries: boolean;\n}): MinikubeAdapterArtifacts {\n const { namespace, buckets, includeSupabaseConnectionEnvEntries } = args;\n const root = 'infra/minikube/k8s/storage/supabase';\n const resourceRoot = 'storage/supabase';\n const bucketsCsv = buckets.join(',');\n const defaultBucket = buckets[0] ?? '';\n\n const envEntries = [\n 'STORAGE_PROVIDER=supabase',\n 'STORAGE_RUNTIME_MODE=local',\n `STORAGE_BUCKETS=${bucketsCsv}`,\n `STORAGE_DEFAULT_BUCKET=${defaultBucket}`,\n 'EXPO_PUBLIC_STORAGE_PROVIDER=supabase',\n `EXPO_PUBLIC_STORAGE_BUCKETS=${bucketsCsv}`,\n `EXPO_PUBLIC_STORAGE_DEFAULT_BUCKET=${defaultBucket}`,\n ];\n\n if (includeSupabaseConnectionEnvEntries) {\n envEntries.push(\n '',\n '# Supabase provider connection details',\n 'SUPABASE_SECRET_SYNC_ENABLED=true',\n 'SUPABASE_URL=',\n 'SUPABASE_ANON_KEY=',\n 'SUPABASE_SERVICE_ROLE_KEY=',\n 'SUPABASE_JWT_SECRET=',\n 'EXPO_PUBLIC_SUPABASE_URL=',\n 'EXPO_PUBLIC_SUPABASE_ANON_KEY=',\n );\n }\n\n return {\n files: [\n {\n path: `${root}/supabase-storage.configmap.yaml`,\n content: getSupabaseStorageConfigMap({\n namespace,\n bucketsCsv,\n defaultBucket,\n }),\n },\n {\n path: `${root}/app-runtime-storage.env.configmap.yaml`,\n content: getRuntimeStorageEnvConfigMap({\n namespace,\n bucketsCsv,\n defaultBucket,\n }),\n },\n ],\n resources: [\n `${resourceRoot}/supabase-storage.configmap.yaml`,\n `${resourceRoot}/app-runtime-storage.env.configmap.yaml`,\n ],\n envEntries,\n warnings: [\n `Storage buckets are configured but not created automatically yet. Ensure buckets exist in Supabase Storage: ${bucketsCsv}.`,\n ],\n };\n}\n\nfunction getSupabaseStorageConfigMap(args: {\n namespace: string;\n bucketsCsv: string;\n defaultBucket: string;\n}) {\n const { namespace, bucketsCsv, defaultBucket } = args;\n\n return `apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: supabase-storage-config\n namespace: ${namespace}\ndata:\n STORAGE_PROVIDER: \"supabase\"\n STORAGE_BUCKETS: \"${escapeYamlDoubleQuoted(bucketsCsv)}\"\n STORAGE_DEFAULT_BUCKET: \"${escapeYamlDoubleQuoted(defaultBucket)}\"\n`;\n}\n\nfunction getRuntimeStorageEnvConfigMap(args: {\n namespace: string;\n bucketsCsv: string;\n defaultBucket: string;\n}) {\n const { namespace, bucketsCsv, defaultBucket } = args;\n\n return `apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: app-runtime-storage-env\n namespace: ${namespace}\ndata:\n STORAGE_PROVIDER: \"supabase\"\n STORAGE_RUNTIME_MODE: \"local\"\n STORAGE_BUCKETS: \"${escapeYamlDoubleQuoted(bucketsCsv)}\"\n STORAGE_DEFAULT_BUCKET: \"${escapeYamlDoubleQuoted(defaultBucket)}\"\n EXPO_PUBLIC_STORAGE_PROVIDER: \"supabase\"\n EXPO_PUBLIC_STORAGE_BUCKETS: \"${escapeYamlDoubleQuoted(bucketsCsv)}\"\n EXPO_PUBLIC_STORAGE_DEFAULT_BUCKET: \"${escapeYamlDoubleQuoted(defaultBucket)}\"\n`;\n}\n\nfunction escapeYamlDoubleQuoted(value: string): string {\n return value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"');\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/adapters/minikube/storage/supabase/index.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gCAAgC,CAAC,IAIhD;IACC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,mCAAmC,EAAE,GAAG,IAAI,CAAC;IACzE,MAAM,IAAI,GAAG,qCAAqC,CAAC;IACnD,MAAM,YAAY,GAAG,kBAAkB,CAAC;IACxC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvC,MAAM,UAAU,GAAG;QACjB,2BAA2B;QAC3B,4BAA4B;QAC5B,mBAAmB,UAAU,EAAE;QAC/B,0BAA0B,aAAa,EAAE;QACzC,uCAAuC;QACvC,+BAA+B,UAAU,EAAE;QAC3C,sCAAsC,aAAa,EAAE;KACtD,CAAC;IAEF,IAAI,mCAAmC,EAAE,CAAC;QACxC,UAAU,CAAC,IAAI,CACb,EAAE,EACF,wCAAwC,EACxC,2BAA2B,EAC3B,gCAAgC,CACjC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,GAAG,IAAI,kCAAkC;gBAC/C,OAAO,EAAE,2BAA2B,CAAC;oBACnC,SAAS;oBACT,UAAU;oBACV,aAAa;iBACd,CAAC;aACH;YACD;gBACE,IAAI,EAAE,GAAG,IAAI,yCAAyC;gBACtD,OAAO,EAAE,6BAA6B,CAAC;oBACrC,SAAS;oBACT,UAAU;oBACV,aAAa;iBACd,CAAC;aACH;SACF;QACD,SAAS,EAAE;YACT,GAAG,YAAY,kCAAkC;YACjD,GAAG,YAAY,yCAAyC;SACzD;QACD,iBAAiB,EAAE,EAAE;QACrB,UAAU;QACV,QAAQ,EAAE;YACR,+GAA+G,UAAU,GAAG;SAC7H;KACF,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAAC,IAIpC;IACC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAEtD,OAAO;;;;eAIM,SAAS;;;sBAGF,sBAAsB,CAAC,UAAU,CAAC;6BAC3B,sBAAsB,CAAC,aAAa,CAAC;CACjE,CAAC;AACF,CAAC;AAED,SAAS,6BAA6B,CAAC,IAItC;IACC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAEtD,OAAO;;;;eAIM,SAAS;;;;sBAIF,sBAAsB,CAAC,UAAU,CAAC;6BAC3B,sBAAsB,CAAC,aAAa,CAAC;;kCAEhC,sBAAsB,CAAC,UAAU,CAAC;yCAC3B,sBAAsB,CAAC,aAAa,CAAC;CAC7E,CAAC;AACF,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAa;IAC3C,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAC/D,CAAC","sourcesContent":["import type { MinikubeAdapterArtifacts } from '../../contracts';\n\nexport function generateSupabaseStorageArtifacts(args: {\n namespace: string;\n buckets: string[];\n includeSupabaseConnectionEnvEntries: boolean;\n}): MinikubeAdapterArtifacts {\n const { namespace, buckets, includeSupabaseConnectionEnvEntries } = args;\n const root = 'infra/minikube/k8s/storage/supabase';\n const resourceRoot = 'storage/supabase';\n const bucketsCsv = buckets.join(',');\n const defaultBucket = buckets[0] ?? '';\n\n const envEntries = [\n 'STORAGE_PROVIDER=supabase',\n 'STORAGE_RUNTIME_MODE=local',\n `STORAGE_BUCKETS=${bucketsCsv}`,\n `STORAGE_DEFAULT_BUCKET=${defaultBucket}`,\n 'EXPO_PUBLIC_STORAGE_PROVIDER=supabase',\n `EXPO_PUBLIC_STORAGE_BUCKETS=${bucketsCsv}`,\n `EXPO_PUBLIC_STORAGE_DEFAULT_BUCKET=${defaultBucket}`,\n ];\n\n if (includeSupabaseConnectionEnvEntries) {\n envEntries.push(\n '',\n '# Supabase provider connection details',\n 'EXPO_PUBLIC_SUPABASE_URL=',\n 'EXPO_PUBLIC_SUPABASE_ANON_KEY=',\n );\n }\n\n return {\n files: [\n {\n path: `${root}/supabase-storage.configmap.yaml`,\n content: getSupabaseStorageConfigMap({\n namespace,\n bucketsCsv,\n defaultBucket,\n }),\n },\n {\n path: `${root}/app-runtime-storage.env.configmap.yaml`,\n content: getRuntimeStorageEnvConfigMap({\n namespace,\n bucketsCsv,\n defaultBucket,\n }),\n },\n ],\n resources: [\n `${resourceRoot}/supabase-storage.configmap.yaml`,\n `${resourceRoot}/app-runtime-storage.env.configmap.yaml`,\n ],\n providerLifecycle: [],\n envEntries,\n warnings: [\n `Storage buckets are configured but not created automatically yet. Ensure buckets exist in Supabase Storage: ${bucketsCsv}.`,\n ],\n };\n}\n\nfunction getSupabaseStorageConfigMap(args: {\n namespace: string;\n bucketsCsv: string;\n defaultBucket: string;\n}) {\n const { namespace, bucketsCsv, defaultBucket } = args;\n\n return `apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: supabase-storage-config\n namespace: ${namespace}\ndata:\n STORAGE_PROVIDER: \"supabase\"\n STORAGE_BUCKETS: \"${escapeYamlDoubleQuoted(bucketsCsv)}\"\n STORAGE_DEFAULT_BUCKET: \"${escapeYamlDoubleQuoted(defaultBucket)}\"\n`;\n}\n\nfunction getRuntimeStorageEnvConfigMap(args: {\n namespace: string;\n bucketsCsv: string;\n defaultBucket: string;\n}) {\n const { namespace, bucketsCsv, defaultBucket } = args;\n\n return `apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: app-runtime-storage-env\n namespace: ${namespace}\ndata:\n STORAGE_PROVIDER: \"supabase\"\n STORAGE_RUNTIME_MODE: \"local\"\n STORAGE_BUCKETS: \"${escapeYamlDoubleQuoted(bucketsCsv)}\"\n STORAGE_DEFAULT_BUCKET: \"${escapeYamlDoubleQuoted(defaultBucket)}\"\n EXPO_PUBLIC_STORAGE_PROVIDER: \"supabase\"\n EXPO_PUBLIC_STORAGE_BUCKETS: \"${escapeYamlDoubleQuoted(bucketsCsv)}\"\n EXPO_PUBLIC_STORAGE_DEFAULT_BUCKET: \"${escapeYamlDoubleQuoted(defaultBucket)}\"\n`;\n}\n\nfunction escapeYamlDoubleQuoted(value: string): string {\n return value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"');\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.2",
4
+ "version": "1.0.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": {
@@ -94,6 +94,9 @@
94
94
  "format:check": "ankhorage-prettier --check .",
95
95
  "prepack": "bun run build",
96
96
  "test": "bun test src",
97
+ "test:e2e": "bun run test:e2e:supabase",
98
+ "test:e2e:minikube": "ANKH_MINIKUBE_ISOLATION=1 bun test src/adapters/minikube/base/twoAppIsolation.integration.test.ts",
99
+ "test:e2e:supabase": "ANKH_MINIKUBE_SUPABASE_ISOLATION=1 bun test src/adapters/minikube/base/twoAppIsolation.integration.test.ts",
97
100
  "typecheck": "bun x tsc --noEmit -p tsconfig.json",
98
101
  "version-packages": "changeset version"
99
102
  },
@@ -2,53 +2,58 @@
2
2
 
3
3
  Generates local Kubernetes artifacts under `infra/minikube/*` from `InfraManifest`.
4
4
 
5
+ ## Ownership Model
6
+
7
+ - One canonical app slug owns one Minikube profile.
8
+ - The generated app runtime lives in namespace `app`.
9
+ - Supabase-owned runtime workloads live in namespace `supabase`.
10
+ - Future self-hosted providers should own deterministic provider namespaces.
11
+
12
+ There is no shared `minikube` profile, no host-level Supabase Compose runtime, and no
13
+ compatibility path for `supabase start`.
14
+
5
15
  ## Structure
6
16
 
7
- - `base/`: namespace, app runtime, kustomization, helper scripts.
17
+ - `base/`: app-owned profile lifecycle, `app` namespace, Supabase namespace, kustomization, helper scripts.
8
18
  - `auth/`: auth provider artifacts (implemented: `supabase`).
9
19
  - `authz/`: authorization engine artifacts (implemented: `cerbos`; `native` warning-only/no resources; `opa` unsupported).
20
+ - `storage/`: storage provider app-runtime config (implemented: `supabase`).
21
+ - `secrets/`: secret-store provider migrations and docs (implemented: `supabase-vault`).
10
22
 
11
- Cerbos policy generation uses app manifest intent (navigator routes/screens + authFlow) when provided by caller.
23
+ Cerbos policy generation uses app manifest intent (navigator routes/screens + authFlow)
24
+ when provided by caller.
12
25
 
13
26
  ## Runtime Scripts
14
27
 
15
- - `scripts/up.sh`: starts minikube (if needed) and applies all generated manifests.
16
- - `scripts/build-app-image.sh`: exports Expo web build from app source and builds Docker image.
17
- - `scripts/port-forward.sh`: forwards `service/app-runtime` to local HTTP (default `127.0.0.1:18080`).
18
- - `scripts/status.sh`: validates kube context/API reachability and shows namespace resources.
19
- - `scripts/down.sh`: deletes generated manifests from the cluster.
20
- - `scripts/supabase-local-env.sh`: reads `supabase status -o env` and writes Supabase keys into `infra/minikube/.env`.
28
+ - `scripts/up.sh`: starts `minikube -p <slug>`, applies manifests, waits for Supabase, runs migrations with `supabase migration up --db-url "$SUPABASE_DB_URL"`, builds/loads the app image, and starts slug-owned port-forwards.
29
+ - `scripts/down.sh`: stops slug-owned port-forwards, then runs `minikube stop -p <slug>`. Persistent profile data remains.
30
+ - `scripts/reset.sh`: requires `ANKH_RESET_CONFIRM=<slug>` and deletes/recreates namespaces `app` and `supabase`, including Supabase DB and Storage PVC data. It does not delete the Minikube profile.
31
+ - `scripts/destroy.sh`: stops slug-owned port-forwards and runs `minikube delete -p <slug>`.
32
+ - `scripts/status.sh`: reports profile, namespace, workload, and port-forward health.
33
+ - `scripts/port-forward.sh`: owns named forwards for `app`, `supabase-gateway`, `studio`, and `db-migration`.
34
+ - `scripts/build-app-image.sh`: exports Expo web build from app source and builds the Docker image.
35
+
36
+ ## Supabase Runtime
21
37
 
22
- Build prerequisites for `build-app-image.sh`:
38
+ Runtime ownership is Kubernetes. Migration authoring/history remains Supabase migration
39
+ files. Migration execution targets the Kubernetes Postgres endpoint via
40
+ `supabase migration up --db-url "$SUPABASE_DB_URL"`.
23
41
 
24
- - `bun` / `bunx`
25
- - `docker`
42
+ The generated manifests are based on the current official Supabase self-hosting Docker
43
+ topology, service documentation, environment-variable contracts, and pinned official
44
+ images. Kubernetes/Helm is treated as community-driven upstream guidance, not an
45
+ official Supabase Kubernetes distribution.
26
46
 
27
47
  ## App Image Behavior
28
48
 
29
- - Default app image: `ankh/<namespace>:dev` (for example `ankh/shop:dev`).
49
+ - Default app image: `ankh/<slug>:dev`.
30
50
  - By default `up.sh` triggers `build-app-image.sh` (`APP_BUILD_ENABLED=true`) before apply.
31
51
  - `build-app-image.sh` runs `bunx expo export --platform web`, then builds via `app-image/Dockerfile`.
32
52
  - `up.sh` syncs runtime image using `APP_IMAGE_SYNC_STRATEGY`:
33
- - `docker-load` (default): loads existing local Docker image into Minikube.
34
- - `minikube-build`: builds exported web artifacts directly into Minikube image store.
53
+ - `docker-load` (default): loads existing local Docker image into the app profile.
54
+ - `minikube-build`: builds exported web artifacts directly into the profile image store.
35
55
  - `none`: skips local image sync.
36
- - Project deletion removes the exact generated `APP_IMAGE` from Minikube and host Docker on a best-effort basis.
37
- - Generated image cleanup defaults can be overridden in `infra/minikube/.env`:
38
- - `APP_IMAGE_CLEANUP_ON_DOWN=false`: disables generated app image cleanup.
39
- - `APP_IMAGE_CLEANUP_MINIKUBE=false`: keeps the Minikube image cache entry.
40
- - `APP_IMAGE_CLEANUP_DOCKER=false`: keeps the host Docker image.
41
- - Cleanup removes only the exact `APP_IMAGE`; it does not run global Docker image or network pruning.
42
56
  - Private registries are supported via optional `.env` keys:
43
- - `APP_BUILD_ENABLED`
44
- - `APP_SOURCE_DIR`
45
- - `SUPABASE_PROJECT_DIR`
46
- - `APP_WEB_EXPORT_DIR`
47
- - `APP_IMAGE_SYNC_STRATEGY`
48
- - `AUTH_RUNTIME_MODE`
49
- - `APP_PORT_FORWARD_LOCAL_PORT`
50
- - `APP_PORT_FORWARD_REMOTE_PORT`
51
- - `SUPABASE_SECRET_SYNC_ENABLED`
52
57
  - `APP_IMAGE_PULL_SECRET_NAME`
53
58
  - `APP_IMAGE_PULL_SECRET_SERVER`
54
59
  - `APP_IMAGE_PULL_SECRET_USERNAME`
@@ -58,16 +63,14 @@ Build prerequisites for `build-app-image.sh`:
58
63
  When pull-secret values are provided, `up.sh` creates/updates the secret and patches
59
64
  `deployment/app-runtime` with `imagePullSecrets`.
60
65
 
61
- When `SUPABASE_SECRET_SYNC_ENABLED=true` and required Supabase keys are present,
62
- `up.sh` creates/updates `secret/supabase-auth-secrets` from env values.
66
+ ## Security Boundary
63
67
 
64
- When `AUTH_RUNTIME_MODE=local` (default) and Supabase keys are missing, `up.sh`
65
- auto-runs `scripts/supabase-local-env.sh`, reloads `.env`, and retries secret sync.
66
- If `supabase/config.toml` is missing in `SUPABASE_PROJECT_DIR`, the helper now runs
67
- `supabase init --yes` automatically before starting local Supabase.
68
+ The app namespace receives only browser-safe Supabase URL and anon key material through
69
+ `Secret/supabase-public-runtime`. Privileged Supabase runtime credentials remain in
70
+ `Secret/supabase-runtime-secrets` in namespace `supabase`.
68
71
 
69
72
  ## Practical Selector Rule
70
73
 
71
- When building config UI or pickers, only show currently supported values from adapter-owned support lists
72
- (`DEPLOYMENT_TARGETS`, `DATABASE_PROVIDERS`, `AUTH_PROVIDERS`, `AUTH_SCOPES`, `AUTHZ_ENGINES`).
73
- Do not show planned values until an adapter path exists in this folder.
74
+ When building config UI or pickers, only show currently supported values from adapter-owned
75
+ support lists (`DEPLOYMENT_TARGETS`, `DATABASE_PROVIDERS`, `AUTH_PROVIDERS`, `AUTH_SCOPES`,
76
+ `AUTHZ_ENGINES`). Do not show planned values until an adapter path exists in this folder.
@@ -42,10 +42,6 @@ export function generateSupabaseAuthArtifacts(args: {
42
42
  profileModel,
43
43
  }),
44
44
  },
45
- {
46
- path: `${root}/supabase-auth.secret.yaml`,
47
- content: getSupabaseSecret(namespace),
48
- },
49
45
  {
50
46
  path: `${root}/app-runtime-auth.env.configmap.yaml`,
51
47
  content: getRuntimeAuthEnvConfigMap({
@@ -72,18 +68,10 @@ export function generateSupabaseAuthArtifacts(args: {
72
68
  ],
73
69
  resources: [
74
70
  `${resourceRoot}/supabase-auth.configmap.yaml`,
75
- `${resourceRoot}/supabase-auth.secret.yaml`,
76
71
  `${resourceRoot}/app-runtime-auth.env.configmap.yaml`,
77
72
  ],
78
- envEntries: [
79
- 'SUPABASE_SECRET_SYNC_ENABLED=true',
80
- 'SUPABASE_URL=',
81
- 'SUPABASE_ANON_KEY=',
82
- 'SUPABASE_SERVICE_ROLE_KEY=',
83
- 'SUPABASE_JWT_SECRET=',
84
- 'EXPO_PUBLIC_SUPABASE_URL=',
85
- 'EXPO_PUBLIC_SUPABASE_ANON_KEY=',
86
- ],
73
+ providerLifecycle: [],
74
+ envEntries: ['EXPO_PUBLIC_SUPABASE_URL=', 'EXPO_PUBLIC_SUPABASE_ANON_KEY='],
87
75
  warnings,
88
76
  };
89
77
  }
@@ -120,23 +108,6 @@ data:
120
108
  `;
121
109
  }
122
110
 
123
- function getSupabaseSecret(namespace: string) {
124
- return `apiVersion: v1
125
- kind: Secret
126
- metadata:
127
- name: supabase-auth-secrets
128
- namespace: ${namespace}
129
- type: Opaque
130
- stringData:
131
- SUPABASE_URL: ""
132
- SUPABASE_ANON_KEY: ""
133
- SUPABASE_SERVICE_ROLE_KEY: ""
134
- SUPABASE_JWT_SECRET: ""
135
- EXPO_PUBLIC_SUPABASE_URL: ""
136
- EXPO_PUBLIC_SUPABASE_ANON_KEY: ""
137
- `;
138
- }
139
-
140
111
  function getRuntimeAuthEnvConfigMap(args: {
141
112
  namespace: string;
142
113
  scope: string;
@@ -197,7 +168,7 @@ This file documents the runtime conventions generated by the minikube Supabase a
197
168
  ## Generated Kubernetes Objects
198
169
 
199
170
  - \`ConfigMap/supabase-auth-config\`: high-level auth metadata.
200
- - \`Secret/supabase-auth-secrets\`: Supabase keys and public runtime keys.
171
+ - \`Secret/supabase-public-runtime\`: browser-safe Supabase URL and anon key material, generated by \`scripts/up.sh\` after local Supabase secrets exist.
201
172
  - \`ConfigMap/app-runtime-auth-env\`: auth runtime feature flags and authz metadata.
202
173
 
203
174
  ## App Runtime Convention
@@ -205,7 +176,7 @@ This file documents the runtime conventions generated by the minikube Supabase a
205
176
  Your app runtime deployment should import both:
206
177
 
207
178
  - \`app-runtime-auth-env\` (configMap)
208
- - \`supabase-auth-secrets\` (secret)
179
+ - \`supabase-public-runtime\` (secret)
209
180
 
210
181
  Example deployment fragment:
211
182
 
@@ -214,7 +185,7 @@ envFrom:
214
185
  - configMapRef:
215
186
  name: app-runtime-auth-env
216
187
  - secretRef:
217
- name: supabase-auth-secrets
188
+ name: supabase-public-runtime
218
189
  \`\`\`
219
190
 
220
191
  The generated base deployment at \`k8s/app/deployment.yaml\` already includes this wiring
@@ -236,18 +207,16 @@ with \`optional: true\` for auth sources.
236
207
  - \`AUTH_PROFILE_PRIMARY_KEY\`
237
208
  - \`AUTH_PROFILE_CREATE_STRATEGY\`
238
209
  - \`AUTH_PROFILE_UPDATE_STRATEGY\`
239
- - \`SUPABASE_SECRET_SYNC_ENABLED\`
240
210
  - \`SUPABASE_URL\`
241
211
  - \`SUPABASE_ANON_KEY\`
242
- - \`SUPABASE_SERVICE_ROLE_KEY\`
243
- - \`SUPABASE_JWT_SECRET\`
244
212
  - \`EXPO_PUBLIC_SUPABASE_URL\`
245
213
  - \`EXPO_PUBLIC_SUPABASE_ANON_KEY\`
246
214
  ${profileSection}
247
- ## Secret Sync
215
+ ## Runtime Secrets
248
216
 
249
- When \`SUPABASE_SECRET_SYNC_ENABLED=true\`, \`scripts/up.sh\` will create/update
250
- \`Secret/supabase-auth-secrets\` from the loaded environment values.
217
+ When Supabase is enabled, \`scripts/up.sh\` creates/updates \`Secret/supabase-public-runtime\`
218
+ with browser-safe values for the app namespace. Privileged Supabase runtime secrets remain in
219
+ the \`supabase\` namespace.
251
220
  `;
252
221
  }
253
222
 
@@ -10,7 +10,7 @@ const PROFILE_POLICY_VERSION = 1;
10
10
  const PROFILE_RECONCILER_VERSION = 1;
11
11
  const PROFILE_ARTIFACT_KEY = 'auth.profile';
12
12
 
13
- export const MANAGED_PROFILE_COLUMNS = [
13
+ const MANAGED_PROFILE_COLUMNS = [
14
14
  'email',
15
15
  'display_name',
16
16
  'first_name',