refactor(host): single-source ChannelPolicy, space-signed file grants, whole-file registration
- all authorization rules (owner/creator, per-channel read/write grants, who may remove whom, delete rules, structure management) live in ChannelPolicy; a test fails if they are reimplemented elsewhere - ChannelInfo carries what the caller may do (can_*), member and invitation lists say who can be removed; clients display it and never derive it - the host no longer stores or calls the file service: it only signs short-lived tickets from space permissions (create/put/get/delete/domain), and keeps an opaque fileDomain reference on the channel - a whole file is registered in one request (last frame header + per-frame length and digest) instead of one request per 1 MiB frame; the signed manifest still has to match every digest - drop file quota/threshold, receipts, reconcile and delete-queue code from the host - contract generator emits constants for enums, error codes, token roles, permissions and share states
This commit is contained in:
1 parent
ccb2c074d6
commit
17638b6e20
36 files changed
+926
-589
No files matched your search
@@ -11,7 +11,7 @@ const fail = (message) => {
|
||||
|
||||
const dtoSources = ['server/src/WebDrop.Api/Json/ApiJson.cs', 'server/src/WebDrop.Core/Channels/Dtos.cs', 'server/src/WebDrop.Core/Channels/Settings.cs', 'server/src/WebDrop.Core/Common/Enums.cs', 'server/src/WebDrop.Core/Spaces/Workspace.cs', 'server/src/WebDrop.Core/Accounts/AccountProfile.cs', 'server/src/WebDrop.Api/Passkeys/PasskeyDtos.cs', 'server/src/WebDrop.Core/Spaces/WorkspaceCrypto.cs', 'server/src/WebDrop.Api/Endpoints/Endpoints.WorkspaceCrypto.cs'];
|
||||
const dtoDigest = createHash('sha256').update(dtoSources.map(path => `${path}\n${read(path).replace(/\r\n/g, '\n')}\n`).join('')).digest('hex');
|
||||
const generatedDigest = /backend-contract-sha256: ([a-f0-9]{64})/.exec(read('web/src/core-bridge/generated/api.ts'))?.[1];
|
||||
const generatedDigest = /backend-contract-sha256: ([a-f0-9]{64})/.exec(read('web/src/api/generated.ts'))?.[1];
|
||||
if (generatedDigest !== dtoDigest) fail('Backend DTOs changed. Regenerate with dotnet run --project tools/ContractGenerator -- .');
|
||||
if (JSON.parse(read('contracts/api.schemas.json'))['x-backend-contract-sha256'] !== dtoDigest) fail('Generated API schemas are stale. Run ContractGenerator.');
|
||||
|
||||
@@ -28,10 +28,10 @@ const backend = read('server/src/WebDrop.Api/Hosting/ApiContract.cs');
|
||||
const backendVersion = /const string Version = "([^"]+)"/.exec(backend)?.[1];
|
||||
if (backendVersion !== contract.version) fail(`backend version ${backendVersion ?? '(missing)'} differs from ${contract.version}.`);
|
||||
|
||||
const frontend = read('web/src/core-bridge/contract.ts');
|
||||
const frontend = read('web/src/api/contract.ts');
|
||||
const supportedMajor = Number(/SUPPORTED_API_CONTRACT_MAJOR\s*=\s*(\d+)/.exec(frontend)?.[1]);
|
||||
if (supportedMajor !== apiMajor) {
|
||||
fail(`backend contract is ${contract.version}; frontend still supports API major ${supportedMajor || '(missing)'}. Update web/src/core-bridge/contract.ts.`);
|
||||
fail(`backend contract is ${contract.version}; frontend still supports API major ${supportedMajor || '(missing)'}. Update web/src/api/contract.ts.`);
|
||||
}
|
||||
|
||||
const tag = process.argv[2];
|
||||
|
||||
Reference in new issue
Block a user