mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-22 19:29:13 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const { test } = require('node:test');
|
||||
|
||||
const {
|
||||
LocalIdentityCredentialAdministrationAuthorizationError,
|
||||
createLocalIdentityCredentialAdministrationService,
|
||||
} = require('@qinglong/local-admin/identity-credential-administration');
|
||||
|
||||
const MUTATION_ID = '82000000-0000-4000-8000-000000000001';
|
||||
const SUBJECT = Object.freeze({ type: 'agent', id: 'agent-planner' });
|
||||
const PRINCIPAL = Object.freeze({
|
||||
subject: { type: 'user', id: 'owner-user' },
|
||||
authenticationId: 'local_identity_admin:test',
|
||||
authenticatedAtMs: 0,
|
||||
expiresAtMs: 120_000,
|
||||
assurance: 'local_console',
|
||||
});
|
||||
|
||||
function projectPolicy(role = 'owner') {
|
||||
return {
|
||||
async resolve() {
|
||||
return {
|
||||
project: {
|
||||
id: 'default',
|
||||
name: 'Default',
|
||||
slug: 'default',
|
||||
status: 'active',
|
||||
version: 1,
|
||||
createdAtMs: 0,
|
||||
updatedAtMs: 0,
|
||||
},
|
||||
binding: {
|
||||
projectId: 'default',
|
||||
subject: PRINCIPAL.subject,
|
||||
version: 1,
|
||||
state: 'active',
|
||||
role,
|
||||
mutationId: 'owner-binding',
|
||||
changedBy: PRINCIPAL.subject,
|
||||
createdAtMs: 0,
|
||||
},
|
||||
};
|
||||
},
|
||||
async append() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test('replays a committed credential after time advances without rereading Identity state', async () => {
|
||||
let nowMs = 1_000;
|
||||
let identityReads = 0;
|
||||
let stored;
|
||||
const repository = {
|
||||
async resolveAuthorityProjectId() {
|
||||
return 'default';
|
||||
},
|
||||
async resolveIdentity() {
|
||||
identityReads += 1;
|
||||
return {
|
||||
subject: SUBJECT,
|
||||
status: 'active',
|
||||
version: 1,
|
||||
createdAtMs: 0,
|
||||
updatedAtMs: 0,
|
||||
};
|
||||
},
|
||||
async resolveIdentityMutation() {
|
||||
return null;
|
||||
},
|
||||
async appendAuthorizedIdentity() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async inspectAuthorizedIdentity() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async resolveCredentialMutation() {
|
||||
return stored ?? null;
|
||||
},
|
||||
async appendAuthorizedCredential(command) {
|
||||
if (!stored) {
|
||||
stored = Object.freeze({
|
||||
projectId: command.authorization.projectId,
|
||||
credential: Object.freeze({ ...command.credential }),
|
||||
mutation: Object.freeze({ ...command.mutation }),
|
||||
delivery: command.delivery,
|
||||
audit: command.audit,
|
||||
});
|
||||
return Object.freeze({ status: 'inserted', ...stored });
|
||||
}
|
||||
assert.deepEqual(command.credential, stored.credential);
|
||||
assert.deepEqual(command.mutation, stored.mutation);
|
||||
assert.deepEqual(command.delivery, stored.delivery);
|
||||
return Object.freeze({ status: 'existing', ...stored });
|
||||
},
|
||||
async inspectAuthorizedCredential() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async resolveDeliveryAcknowledgement() {
|
||||
return null;
|
||||
},
|
||||
async appendAuthorizedDeliveryAcknowledgement() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async record() {},
|
||||
};
|
||||
const service = createLocalIdentityCredentialAdministrationService(
|
||||
projectPolicy(),
|
||||
repository,
|
||||
{ now: () => nowMs },
|
||||
);
|
||||
const request = {
|
||||
projectId: 'default',
|
||||
operation: 'issue',
|
||||
credentialId: 'agent-planner-primary',
|
||||
target: SUBJECT,
|
||||
expectedCurrentVersion: 0,
|
||||
pepperKeyId: 'owner-v1',
|
||||
secretDigest: 'a'.repeat(64),
|
||||
deliveryDigest: 'b'.repeat(64),
|
||||
notBeforeAtMs: 1_000,
|
||||
expiresAtMs: 61_000,
|
||||
mutationId: MUTATION_ID,
|
||||
requestId: 'identity-credential-replay',
|
||||
principal: PRINCIPAL,
|
||||
};
|
||||
|
||||
assert.equal((await service.changeCredential(request)).status, 'inserted');
|
||||
nowMs = 30_000;
|
||||
assert.equal((await service.changeCredential(request)).status, 'existing');
|
||||
assert.equal(identityReads, 1);
|
||||
assert.equal(stored.mutation.createdAtMs, 1_000);
|
||||
assert.equal(stored.credential.notBeforeAtMs, 1_000);
|
||||
});
|
||||
|
||||
test('inspects current versions only after Owner authorization', async () => {
|
||||
const audits = [];
|
||||
const identity = Object.freeze({
|
||||
subject: SUBJECT,
|
||||
status: 'active',
|
||||
version: 7,
|
||||
createdAtMs: 100,
|
||||
updatedAtMs: 700,
|
||||
});
|
||||
const credential = Object.freeze({
|
||||
credentialId: 'agent-planner-primary',
|
||||
version: 5,
|
||||
pepperKeyId: 'owner-v1',
|
||||
state: 'active',
|
||||
subject: SUBJECT,
|
||||
subjectStatus: 'active',
|
||||
secretDigest: 'a'.repeat(64),
|
||||
createdAtMs: 500,
|
||||
notBeforeAtMs: 500,
|
||||
expiresAtMs: 60_500,
|
||||
});
|
||||
const repository = {
|
||||
async resolveAuthorityProjectId() {
|
||||
return 'default';
|
||||
},
|
||||
async resolveIdentity() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async resolveIdentityMutation() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async appendAuthorizedIdentity() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async inspectAuthorizedIdentity(command) {
|
||||
assert.equal(command.audit.operationId, 'identity.inspect');
|
||||
assert.equal(command.authorization.actor.id, 'owner-user');
|
||||
return { identity, audit: command.audit };
|
||||
},
|
||||
async resolveCredentialMutation() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async appendAuthorizedCredential() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async inspectAuthorizedCredential(command) {
|
||||
assert.equal(command.audit.operationId, 'credential.inspect');
|
||||
assert.equal(command.credentialId, credential.credentialId);
|
||||
return { credential, audit: command.audit };
|
||||
},
|
||||
async resolveDeliveryAcknowledgement() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async appendAuthorizedDeliveryAcknowledgement() {
|
||||
throw new Error('not used');
|
||||
},
|
||||
async record(audit) {
|
||||
audits.push(audit);
|
||||
},
|
||||
};
|
||||
const owner = createLocalIdentityCredentialAdministrationService(
|
||||
projectPolicy(),
|
||||
repository,
|
||||
{ now: () => 1_000 },
|
||||
);
|
||||
const identityResult = await owner.inspectIdentity({
|
||||
projectId: 'default',
|
||||
target: SUBJECT,
|
||||
auditEventId: '82000000-0000-4000-8000-000000000002',
|
||||
requestId: 'identity-inspect',
|
||||
principal: PRINCIPAL,
|
||||
});
|
||||
const credentialResult = await owner.inspectCredential({
|
||||
projectId: 'default',
|
||||
credentialId: credential.credentialId,
|
||||
auditEventId: '82000000-0000-4000-8000-000000000003',
|
||||
requestId: 'credential-inspect',
|
||||
principal: PRINCIPAL,
|
||||
});
|
||||
assert.equal(identityResult.identity.version, 7);
|
||||
assert.equal(credentialResult.credential.version, 5);
|
||||
|
||||
const nonOwner = createLocalIdentityCredentialAdministrationService(
|
||||
projectPolicy('admin'),
|
||||
repository,
|
||||
{ now: () => 1_000 },
|
||||
);
|
||||
await assert.rejects(
|
||||
nonOwner.inspectIdentity({
|
||||
projectId: 'default',
|
||||
target: SUBJECT,
|
||||
auditEventId: '82000000-0000-4000-8000-000000000004',
|
||||
requestId: 'identity-inspect-denied',
|
||||
principal: PRINCIPAL,
|
||||
}),
|
||||
LocalIdentityCredentialAdministrationAuthorizationError,
|
||||
);
|
||||
assert.equal(audits.length, 1);
|
||||
assert.equal(audits[0].operationId, 'identity.inspect');
|
||||
assert.equal(audits[0].outcome, 'denied');
|
||||
|
||||
const foreignProjectOwner =
|
||||
createLocalIdentityCredentialAdministrationService(
|
||||
projectPolicy(),
|
||||
repository,
|
||||
{ now: () => 1_000 },
|
||||
);
|
||||
await assert.rejects(
|
||||
foreignProjectOwner.inspectCredential({
|
||||
projectId: 'secondary',
|
||||
credentialId: credential.credentialId,
|
||||
auditEventId: '82000000-0000-4000-8000-000000000005',
|
||||
requestId: 'credential-inspect-foreign-project',
|
||||
principal: PRINCIPAL,
|
||||
}),
|
||||
LocalIdentityCredentialAdministrationAuthorizationError,
|
||||
);
|
||||
assert.equal(audits.length, 2);
|
||||
assert.deepEqual(audits[1].reasons, ['instance_authority_project_required']);
|
||||
});
|
||||
Reference in New Issue
Block a user