@ankhorage/infra 0.3.2 → 0.3.4

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 (48) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +2 -2
  3. package/dist/adapters/minikube/auth/supabase/index.d.ts.map +1 -1
  4. package/dist/adapters/minikube/auth/supabase/index.js +14 -163
  5. package/dist/adapters/minikube/auth/supabase/index.js.map +1 -1
  6. package/dist/adapters/minikube/auth/supabase/profile.d.ts +21 -0
  7. package/dist/adapters/minikube/auth/supabase/profile.d.ts.map +1 -0
  8. package/dist/adapters/minikube/auth/supabase/profile.js +452 -0
  9. package/dist/adapters/minikube/auth/supabase/profile.js.map +1 -0
  10. package/dist/adapters/minikube/authz/cerbos/index.d.ts +1 -1
  11. package/dist/adapters/minikube/authz/cerbos/index.d.ts.map +1 -1
  12. package/dist/adapters/minikube/authz/cerbos/index.js +5 -3
  13. package/dist/adapters/minikube/authz/cerbos/index.js.map +1 -1
  14. package/dist/adapters/minikube/authz/index.d.ts +1 -1
  15. package/dist/adapters/minikube/authz/index.d.ts.map +1 -1
  16. package/dist/adapters/minikube/authz/index.js +1 -1
  17. package/dist/adapters/minikube/authz/index.js.map +1 -1
  18. package/dist/adapters/minikube/base/index.d.ts.map +1 -1
  19. package/dist/adapters/minikube/base/index.js +850 -54
  20. package/dist/adapters/minikube/base/index.js.map +1 -1
  21. package/dist/adapters/minikube/index.js +2 -1
  22. package/dist/adapters/minikube/index.js.map +1 -1
  23. package/dist/infraValidation.js +1 -1
  24. package/dist/infraValidation.js.map +1 -1
  25. package/dist/project.d.ts.map +1 -1
  26. package/dist/project.js +1 -18
  27. package/dist/project.js.map +1 -1
  28. package/dist/testSupport.d.ts.map +1 -1
  29. package/dist/testSupport.js +0 -6
  30. package/dist/testSupport.js.map +1 -1
  31. package/dist/types.d.ts +1 -1
  32. package/dist/types.d.ts.map +1 -1
  33. package/dist/types.js.map +1 -1
  34. package/package.json +2 -2
  35. package/src/adapters/minikube/auth/supabase/index.test.ts +152 -18
  36. package/src/adapters/minikube/auth/supabase/index.ts +18 -205
  37. package/src/adapters/minikube/auth/supabase/profile.integration.test.ts +860 -0
  38. package/src/adapters/minikube/auth/supabase/profile.ts +526 -0
  39. package/src/adapters/minikube/authz/cerbos/index.ts +7 -5
  40. package/src/adapters/minikube/authz/index.ts +2 -2
  41. package/src/adapters/minikube/base/index.test.ts +100 -6
  42. package/src/adapters/minikube/base/index.ts +880 -54
  43. package/src/adapters/minikube/index.ts +3 -1
  44. package/src/index.test.ts +13 -2
  45. package/src/infraValidation.ts +1 -1
  46. package/src/project.ts +2 -22
  47. package/src/testSupport.ts +0 -6
  48. package/src/types.ts +1 -1
@@ -50,17 +50,101 @@ describe('generateMinikubeBaseArtifacts Supabase local ports', () => {
50
50
  expect(script).toContain(
51
51
  'Supabase local start failed. Stopping stale local stack and retrying once...',
52
52
  );
53
- expect(script).toContain('supabase stop --no-backup >/dev/null 2>&1 || true');
53
+ expect(script).toContain(
54
+ 'supabase --workdir "${SUPABASE_PROJECT_DIR}" stop --no-backup >/dev/null 2>&1 || true',
55
+ );
54
56
  expect(script).toContain('Supabase local start failed after retry.');
55
57
  expect(script).toContain('start_supabase_local_stack');
56
- expect(countOccurrences(script, 'supabase start >/dev/null')).toBe(2);
57
- expect(countOccurrences(script, 'supabase stop --no-backup')).toBe(1);
58
+ expect(
59
+ countOccurrences(script, 'supabase --workdir "${SUPABASE_PROJECT_DIR}" start >/dev/null'),
60
+ ).toBe(2);
61
+ expect(
62
+ countOccurrences(script, 'supabase --workdir "${SUPABASE_PROJECT_DIR}" stop --no-backup'),
63
+ ).toBe(1);
64
+ });
65
+
66
+ test('generates canonical Supabase workdir and required CLI capability checks', () => {
67
+ const script = getGeneratedFileContent('chess', 'infra/minikube/scripts/supabase-local-env.sh');
68
+
69
+ expect(script).toContain('SUPABASE_PROJECT_DIR="${SUPABASE_PROJECT_DIR:-${ROOT_DIR}}"');
70
+ expect(script).toContain('supabase CLI >= 2.106.0 is required');
71
+ expect(script).toContain('supabase CLI does not support required global --workdir flag');
72
+ expect(script).toContain('supabase CLI does not support required migration up --local command');
73
+ expect(script).toContain('psql is required but not installed');
74
+ expect(script).toContain('supabase --workdir "${SUPABASE_PROJECT_DIR}" init --yes');
75
+ expect(script).toContain('supabase --workdir "${SUPABASE_PROJECT_DIR}" migration up --local');
76
+ expect(script).toContain('psql "${SUPABASE_DB_URL}" -v ON_ERROR_STOP=1 -q -f "${sql_file}"');
77
+ });
78
+
79
+ test('generates profile reconciliation and live verification flow when profile table is configured', () => {
80
+ const overrides = {
81
+ auth: {
82
+ profile: {
83
+ table: 'profiles',
84
+ fields: ['email', 'displayName'],
85
+ },
86
+ },
87
+ } satisfies Partial<InfraManifestInput>;
88
+ const script = getGeneratedFileContent(
89
+ 'chess',
90
+ 'infra/minikube/scripts/supabase-local-env.sh',
91
+ overrides,
92
+ );
93
+ const status = getGeneratedFileContent('chess', 'infra/minikube/scripts/status.sh', overrides);
94
+
95
+ expect(script).toContain('SUPABASE_PROFILE_ENABLED="true"');
96
+ expect(script).toContain(
97
+ 'SUPABASE_PROFILE_RECONCILE_FILE="${SUPABASE_PROJECT_DIR}/supabase/generated/auth_profiles.sql"',
98
+ );
99
+ expect(script).toContain('Generated profile reconciliation');
100
+ expect(script).toContain('SQL file: ${sql_file}');
101
+ expect(script).toContain('Supabase project workdir: ${SUPABASE_PROJECT_DIR}');
102
+ expect(script).toContain('Exit status: ${status}');
103
+ expect(script).toContain('ankhorage_internal.generated_schema_state');
104
+ expect(script).toContain('check_immutable_migrations_applied');
105
+ expect(status).toContain('- immutable migrations: applied');
106
+ expect(status).toContain('- immutable migrations: pending');
107
+ expect(status).toContain('- profile reconciliation: applied, checksum matches');
108
+ expect(status).toContain('- profile schema: verified');
109
+ expect(status).toContain('reserved conflicting identity table public.users exists');
110
+ expect(status).toContain('stale managed profile column');
111
+ expect(status).toContain('own-profile SELECT policy is missing or has unsafe definition');
112
+ expect(status).toContain('unexpected profile table RLS policy exists');
113
+ expect(status).toContain(
114
+ "has_any_column_privilege('anon', format('public.%I', profile_table), 'SELECT')",
115
+ );
116
+ expect(status).toContain(
117
+ "has_any_column_privilege('anon', format('public.%I', profile_table), 'INSERT')",
118
+ );
119
+ expect(status).toContain(
120
+ "has_any_column_privilege('anon', format('public.%I', profile_table), 'UPDATE')",
121
+ );
122
+ expect(status).toContain(
123
+ "has_any_column_privilege('anon', format('public.%I', profile_table), 'REFERENCES')",
124
+ );
125
+ expect(status).toContain(
126
+ "has_any_column_privilege('authenticated', format('public.%I', profile_table), 'INSERT')",
127
+ );
128
+ expect(status).toContain(
129
+ "has_any_column_privilege('authenticated', format('public.%I', profile_table), 'REFERENCES')",
130
+ );
131
+ expect(status).toContain(
132
+ 'authenticated role must not have profile table INSERT, DELETE, or REFERENCES privilege',
133
+ );
134
+ expect(status).toContain(
135
+ 'authenticated role has unexpected UPDATE privilege on profile column',
136
+ );
137
+ expect(status).toContain('generated trigger function execute privilege must be revoked');
58
138
  });
59
139
  });
60
140
 
61
- function getGeneratedFileContent(namespace: string, filePath: string): string {
141
+ function getGeneratedFileContent(
142
+ namespace: string,
143
+ filePath: string,
144
+ overrides: Partial<InfraManifestInput> = {},
145
+ ): string {
62
146
  const artifact = generateMinikubeBaseArtifacts({
63
- manifest: createInfraManifest(),
147
+ manifest: createInfraManifest(overrides),
64
148
  namespace,
65
149
  extraResources: [],
66
150
  extraEnvEntries: [],
@@ -77,7 +161,7 @@ function countOccurrences(source: string, needle: string): number {
77
161
  return source.split(needle).length - 1;
78
162
  }
79
163
 
80
- function createInfraManifest(): InfraManifestInput {
164
+ function createInfraManifest(overrides: Partial<InfraManifestInput> = {}): InfraManifestInput {
81
165
  return {
82
166
  deployment: {
83
167
  target: 'minikube',
@@ -99,5 +183,15 @@ function createInfraManifest(): InfraManifestInput {
99
183
  cdn: false,
100
184
  },
101
185
  plugins: [],
186
+ ...overrides,
187
+ auth: {
188
+ scope: 'global',
189
+ provider: 'supabase',
190
+ authorization: {
191
+ kind: 'RBAC',
192
+ engine: 'native',
193
+ },
194
+ ...overrides.auth,
195
+ },
102
196
  };
103
197
  }