js-rigor: partial-graph policy limits now enforce; binary-partial pins
- Arbiter constructor and setPartialGraphPolicy dropped maxNodes, maxRelations, and reservedRelations — the partial-graph context always saw the 1000/2000 defaults, silently disabling configured DoS guards. Both paths now carry the limits through; policy limits test pins constructor + setter enforcement and custom reservedRelations.
This commit is contained in:
+7
-1
@@ -130,7 +130,13 @@ export class Arbiter {
|
||||
|| 'deterministic',
|
||||
reducers: {
|
||||
...(options?.partialGraphPolicy?.reducers || {})
|
||||
}
|
||||
},
|
||||
// Size/reserved limits must survive construction: the partial-graph
|
||||
// context reads them from the policy, and dropping them silently
|
||||
// disabled configured DoS guards (defaults 1000/2000 applied).
|
||||
maxNodes: options?.partialGraphPolicy?.maxNodes,
|
||||
maxRelations: options?.partialGraphPolicy?.maxRelations,
|
||||
reservedRelations: options?.partialGraphPolicy?.reservedRelations
|
||||
};
|
||||
|
||||
this.snapshotEnabled = false;
|
||||
|
||||
@@ -62,7 +62,10 @@ export class ArbiterConfig {
|
||||
|
||||
this.arbiter.partialGraphPolicy = {
|
||||
conflict_mode: conflictMode,
|
||||
reducers
|
||||
reducers,
|
||||
maxNodes: next.maxNodes !== undefined ? next.maxNodes : current.maxNodes,
|
||||
maxRelations: next.maxRelations !== undefined ? next.maxRelations : current.maxRelations,
|
||||
reservedRelations: next.reservedRelations !== undefined ? next.reservedRelations : current.reservedRelations
|
||||
};
|
||||
return this.arbiter.partialGraphPolicy;
|
||||
}
|
||||
|
||||
@@ -274,6 +274,46 @@ describe('Partial-graph overlay semantics (rigor)', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('POLICY LIMITS: maxNodes/maxRelations enforce and reservedRelations customizes', () => {
|
||||
const four = [
|
||||
{ src: 'u:0', relation: 'owner', dst: 'doc:0', possibility: 0.9 },
|
||||
{ src: 'u:0', relation: 'owner', dst: 'doc:0', possibility: 0.8 },
|
||||
{ src: 'u:0', relation: 'owner', dst: 'doc:0', possibility: 0.7 },
|
||||
{ src: 'u:0', relation: 'owner', dst: 'doc:0', possibility: 0.6 }
|
||||
];
|
||||
const mk = (policy) => {
|
||||
const a = new Arbiter(policy ? { partialGraphPolicy: policy } : {});
|
||||
a.addNode('u:0', 'user');
|
||||
a.addNode('doc:0', 'doc');
|
||||
a.setRelationConfig('can_read', { type: 'direct', relation: 'owner' });
|
||||
return a;
|
||||
};
|
||||
assert.throws(
|
||||
() => mk({ maxRelations: 3 }).check('u:0', 'can_read', 'doc:0', { partialGraph: { relations: four } }),
|
||||
/exceeds max relations/,
|
||||
'constructor maxRelations enforces'
|
||||
);
|
||||
assert.throws(
|
||||
() => mk({ maxNodes: 1 }).check('u:0', 'can_read', 'doc:0', {
|
||||
partialGraph: { nodes: [{ key: 'g:a' }, { key: 'g:b' }], relations: four }
|
||||
}),
|
||||
/exceeds max nodes/,
|
||||
'constructor maxNodes enforces'
|
||||
);
|
||||
const viaSetter = mk();
|
||||
viaSetter.setPartialGraphPolicy({ maxRelations: 2 });
|
||||
assert.throws(
|
||||
() => viaSetter.check('u:0', 'can_read', 'doc:0', { partialGraph: { relations: four } }),
|
||||
/exceeds max relations/,
|
||||
'setter maxRelations enforces'
|
||||
);
|
||||
const customReserved = mk({ reservedRelations: ['owner'] });
|
||||
const r = customReserved.check('u:0', 'can_read', 'doc:0', {
|
||||
partialGraph: { relations: [{ src: 'u:0', relation: 'owner', dst: 'doc:0', possibility: 0.9 }] }
|
||||
});
|
||||
assert.equal(r.possibility, 0, 'custom reservedRelations skips owner');
|
||||
});
|
||||
|
||||
it('PROPERTY CAMPAIGN: direct/chain overlay parity under persistent+partial mutations', async () => {
|
||||
const result = await rigor.campaign(
|
||||
[rigor.object('graph', makeWrapper, [
|
||||
|
||||
Reference in New Issue
Block a user