test(runtime): a group join and leave rewrite no content rows - #8664
Conversation
Asserts the membership-cost invariant on real serialized rows: every content row is byte-identical across both a join and a leave while the member's visibility flips, which is what distinguishes a group grant plus a membership edge from per-root grants proportional to the group's data. Documents allow_group in the multi-user skill, where the per-root grant it replaces is taught. Closes jaseci-labs#8460
Bare top-level statements aren't valid at module scope, the connect operator was doubled (++>:Type():++> instead of +>:Type:+>), and doc/ user_root were never declared - none of it had been run through jac check. Wrapped in functions with a self-contained Doc type, fixed the operator, and swapped user_root for root (the joining principal's own root, matching every other cross-user example in this file).
jaseci-labs#8682 dissolved jaclang/jac0core and jaclang/runtimelib. This test named four modules by their old paths, so it merged clean and would have failed at import: archetype and runtime moved to jaclang/runtime, context moved to jaclang/runtime, and serializer moved to jaclang/data.
No source change. `passes-native`/`test-runtime` failed on a fault that cannot originate in this branch (see the PR comment); this re-triggers the lane so the real signal is visible.
|
CI note: the red lanes on this PR are not from this branch. Recording the
1.
A markdown file cannot cause that. Both #8654 and #8664 went 2. Whole-tree
Same 913 files, same "912 passed, 1 failed", different victim each run, and Other people's PRs look green only because their runs predate 0.37 (newest is Happy to file the |
jac check's fork work pool assigns files to workers differently on every run, and a worker serving a file with an incomplete stub prelude reports stdlib types as Self/<Unknown>. One unrelated file fails per run. No source change here.
Summary
Closes #8460, as its own section 6.1 predicted: the group key turned out not
to be needed, because
allow_groupplus edge-based membership landed in #8598(merged yesterday) with the pushdown. What #8460 asked for and did not get is
the proof and the app-facing documentation, which is what this PR adds.
I checked the mechanism against the issue's complaint before writing anything:
entry per object rather than N.
_groups_of), so a join or aleave writes no content row at all - the O(members x anchors) cost the issue
measured (100 grant calls per join, 100 per leave, every row's
propschanged) is gone.
accessstill living inside thepropsJSONB - no longer has the consequence it names, because membership nolonger touches
props. Movingaccessto its own column stays a legitimatestorage follow-up but is not needed for I2; I did not fold it in here.
So the honest close is evidence plus docs, not a new mechanism.
What this adds
tests/runtimelib/test_group_membership_cost.jacseeds 8 group-shareditems, fingerprints every content row (sha256 of the serialized props, which
is what a store write sees), then joins a member and leaves again.
assertion names the drifting rows if it ever fails).
join, 0 after the leave), so the invariant is not vacuous - the existing
[Arch] Graph traversal: page the adjacency, fold the query, make object-space cost visible (#8595) #8598 test asserts a group grant reaches a member, but nothing asserted
the cost invariant.
allow_groupdocumented injac-sv-multi-user, next to the per-rootallow_rootsection it replaces for audiences. It was only mentioned injac-sv-persistence(a performance aside), so an app author reading themulti-user skill - the one that teaches sharing - would not find it and
would reach for
allow_rootper member, which is exactly how the issue'sO(N x M) pattern gets written.
Result on the rig: 1 passed.
Could this have been less code?
It is test + docs only; no runtime change. The alternative was implementing
the issue's option 2 (a
Permission.groupsmap keyed by group id) - whichalready exists as of #8598, so writing it again would have been duplicate
mechanism. Verified before starting rather than after.
Deleted
allow_rootpath, whichis still correct for sharing with one named user; the docs now say which to
reach for. Nothing about the previous behavior was asserted anywhere, so no
test became stale.
What else could this break
monolith vs microservice, kind vs EKS, embedded vs external DB and replica
count are all unaffected.
ExecutionContexthelperstest_acl_pushdown.jacuses, so it exercises thereal serializer and the real group resolution rather than asserting on
internals.
Serializer.serialize(anchor, include_type=True), which is what_serializewrites intoprops. If that ever stops being the write path,this test would silently stop measuring the right thing.