@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.
- package/CHANGELOG.md +12 -0
- package/README.md +2 -2
- package/dist/adapters/minikube/auth/supabase/index.d.ts.map +1 -1
- package/dist/adapters/minikube/auth/supabase/index.js +14 -163
- package/dist/adapters/minikube/auth/supabase/index.js.map +1 -1
- package/dist/adapters/minikube/auth/supabase/profile.d.ts +21 -0
- package/dist/adapters/minikube/auth/supabase/profile.d.ts.map +1 -0
- package/dist/adapters/minikube/auth/supabase/profile.js +452 -0
- package/dist/adapters/minikube/auth/supabase/profile.js.map +1 -0
- package/dist/adapters/minikube/authz/cerbos/index.d.ts +1 -1
- package/dist/adapters/minikube/authz/cerbos/index.d.ts.map +1 -1
- package/dist/adapters/minikube/authz/cerbos/index.js +5 -3
- package/dist/adapters/minikube/authz/cerbos/index.js.map +1 -1
- package/dist/adapters/minikube/authz/index.d.ts +1 -1
- package/dist/adapters/minikube/authz/index.d.ts.map +1 -1
- package/dist/adapters/minikube/authz/index.js +1 -1
- package/dist/adapters/minikube/authz/index.js.map +1 -1
- package/dist/adapters/minikube/base/index.d.ts.map +1 -1
- package/dist/adapters/minikube/base/index.js +850 -54
- package/dist/adapters/minikube/base/index.js.map +1 -1
- package/dist/adapters/minikube/index.js +2 -1
- package/dist/adapters/minikube/index.js.map +1 -1
- package/dist/infraValidation.js +1 -1
- package/dist/infraValidation.js.map +1 -1
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +1 -18
- package/dist/project.js.map +1 -1
- package/dist/testSupport.d.ts.map +1 -1
- package/dist/testSupport.js +0 -6
- package/dist/testSupport.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/src/adapters/minikube/auth/supabase/index.test.ts +152 -18
- package/src/adapters/minikube/auth/supabase/index.ts +18 -205
- package/src/adapters/minikube/auth/supabase/profile.integration.test.ts +860 -0
- package/src/adapters/minikube/auth/supabase/profile.ts +526 -0
- package/src/adapters/minikube/authz/cerbos/index.ts +7 -5
- package/src/adapters/minikube/authz/index.ts +2 -2
- package/src/adapters/minikube/base/index.test.ts +100 -6
- package/src/adapters/minikube/base/index.ts +880 -54
- package/src/adapters/minikube/index.ts +3 -1
- package/src/index.test.ts +13 -2
- package/src/infraValidation.ts +1 -1
- package/src/project.ts +2 -22
- package/src/testSupport.ts +0 -6
- 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(
|
|
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(
|
|
57
|
-
|
|
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(
|
|
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
|
}
|