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',
|
|| 'deterministic',
|
||||||
reducers: {
|
reducers: {
|
||||||
...(options?.partialGraphPolicy?.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;
|
this.snapshotEnabled = false;
|
||||||
|
|||||||
@@ -62,7 +62,10 @@ export class ArbiterConfig {
|
|||||||
|
|
||||||
this.arbiter.partialGraphPolicy = {
|
this.arbiter.partialGraphPolicy = {
|
||||||
conflict_mode: conflictMode,
|
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;
|
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 () => {
|
it('PROPERTY CAMPAIGN: direct/chain overlay parity under persistent+partial mutations', async () => {
|
||||||
const result = await rigor.campaign(
|
const result = await rigor.campaign(
|
||||||
[rigor.object('graph', makeWrapper, [
|
[rigor.object('graph', makeWrapper, [
|
||||||
|
|||||||
Reference in New Issue
Block a user