| 12345678910111213141516171819202122232425262728293031323334353637383940414243 |
- // Only the two new public board action functions; no changes to existing functions, schemas or ACLs.
- import fs from 'node:fs';
- import path from 'node:path';
- import crypto from 'node:crypto';
- import { ROOT, request } from './platform-client.mjs';
- const sha = (s) => crypto.createHash('sha256').update(s).digest('hex');
- const apply = process.argv.includes('--apply');
- const manifest = JSON.parse(fs.readFileSync(path.join(ROOT, 'dist/manifest.json')));
- const names = ['ksfSetPublicOpportunityStatus', 'ksfRatePublicOpportunity'];
- const output = path.join(ROOT, 'evidence/board-actions-' + Date.now() + '.json');
- const journal = { ok: false, readOnly: !apply, at: new Date().toISOString(), businessWrites: 0, schemaChanges: 0, permissionChanges: 0, functions: [] };
- try {
- const schemas = await request('GET', '/schemas');
- for (const name of names) {
- const entry = manifest.functions.find((f) => f.name === name);
- if (!entry || entry.path !== '/' + name) throw Error('BAD_MANIFEST');
- const code = fs.readFileSync(path.join(ROOT, entry.file), 'utf8');
- if (sha(code) !== entry.sha256) throw Error('HASH_MISMATCH');
- new Function(code);
- const query = new URLSearchParams({ where: JSON.stringify({ $or: [{ name }, { path: '/' + name }] }), limit: '3' });
- const matches = (await request('GET', '/classes/Function?' + query)).results;
- if (matches.length > 1 || matches.some((f) => f.name !== name || f.path !== '/' + name || f.code !== code)) throw Error('UNKNOWN_FUNCTION_VERSION');
- journal.functions.push({ name, path: '/' + name, sha256: sha(code), objectId: matches[0]?.objectId || null, action: matches.length ? 'unchanged' : 'create' });
- }
- if (apply) for (const entry of journal.functions) {
- if (entry.action === 'unchanged') continue;
- const def = manifest.functions.find((f) => f.name === entry.name), code = fs.readFileSync(path.join(ROOT, def.file), 'utf8');
- const created = await request('POST', '/classes/Function', { name: entry.name, path: entry.path, code, ACL: {} });
- entry.objectId = created.objectId;
- fs.writeFileSync(output, JSON.stringify(journal, null, 2), { mode: 0o600 });
- const read = await request('GET', '/classes/Function/' + entry.objectId);
- if (read.code !== code || read.path !== entry.path || read.name !== entry.name) throw Error('READBACK_MISMATCH');
- entry.verified = true;
- }
- if (JSON.stringify((await request('GET', '/schemas')).results) !== JSON.stringify(schemas.results)) throw Error('SCHEMA_OR_PERMISSION_CHANGE');
- journal.ok = true; journal.schemaAndPermissionsPreserved = true;
- fs.writeFileSync(output, JSON.stringify(journal, null, 2), { mode: 0o600 });
- console.log(JSON.stringify(journal));
- } catch (error) {
- journal.error = { code: /^[A-Z_]+$/.test(error.message) ? error.message : 'DEPLOY_STOPPED' };
- fs.writeFileSync(output, JSON.stringify(journal, null, 2), { mode: 0o600 });
- console.error(JSON.stringify(journal)); process.exitCode = 1;
- }
|