test(fga): live coverage for dry-run, ABAC and cache routing - #350
test(fga): live coverage for dry-run, ABAC and cache routing#350yosiharan wants to merge 8 commits into
Conversation
|
@shuni review |
|
🐕 Review complete — View session on Shuni Portal 🐾 |
There was a problem hiding this comment.
🐕 Shuni's Review
Adds FGALiveTest — GDrive schema round trip, ABAC context, dry-run and the three-tier FGA cache routing coverage. I traced all 17 GDrive expectations against the DSL (all correct), and the 6 routed calls in the negative test match exactly the getFgaUri call sites in FGAServiceImpl/AuthzServiceImpl. Good bones! 🦴
Sniffed out 2 issues:
- 1 🟡 MEDIUM:
@AfterAllleaves the shared project with no schema, which another live suite dereferences unguarded - 1 🟢 LOW:
assertNotNullon a wire-nullable list
See inline comments for details. Woof!
Declared coverage: FULL — 1/1 changed files reviewed.
|
@shuni review |
|
🐕 Review complete — View session on Shuni Portal 🐾 |
There was a problem hiding this comment.
🐕 Shuni's Review
FGALiveTest ports the Go GDrive/ABAC coverage and adds dry-run plus the three-tier cache-routing tiers. Re-traced all 17 GDrive expectations against the DSL (correct), and the 7 assertThrows map exactly onto the 6 getFgaUri call sites. The previous round's two findings are addressed — no schema deletion, assertDoesNotThrow on the non-routed authz call. Good bones! 🦴
Sniffed out 3 issues:
- 1 🟡 MEDIUM: retrying on
ServerCommonExceptionmakes deterministic failures cost ~30 min across the matrix - 2 🟢 LOW: nullable
targetson the deny-pathwhoCanAccess; two byte-identical cache round-trip tests
See inline comments for details. Woof!
Declared coverage: FULL — 1/1 changed files reviewed.
|
@shuni review |
|
🐕 Review complete — View session on Shuni Portal 🐾 |
There was a problem hiding this comment.
🐕 Shuni's Review
Third pass on FGALiveTest. Both prior LOWs are fixed (assertRoundTripWorks now shared, deny-path whoCanAccess null-guarded), and the retry cost concern is materially addressed — suspendForMs is 10s and AssertionFailedError is an Error, so assertion failures were never retried in the first place; only a genuine ServerCommonException costs ~20s per test.
Re-verified this round: all 5 model constructor arg orders against the Lombok field orders, the 17 GDrive expectations against the DSL, and the 7 assertThrows against the 6 getFgaUri call sites. getConditions() is guaranteed non-null by FGAServiceImpl.loadSchema, so line 198 is safe. Java 8 leg, checkstyle's 120-col limit and surefire's *Test pattern all clear. Good bones! 🦴
Sniffed out 1 issue:
- 1 🟢 LOW: one assertion in the ABAC-through-authz block passes on an empty result
See inline comments for details. Woof!
Declared coverage: FULL — 1/1 changed files reviewed.
|
@shuni review |
|
🐕 Review complete — View session on Shuni Portal 🐾 |
There was a problem hiding this comment.
🐕 Shuni's Review
Fourth pass on FGALiveTest. The one open LOW is genuinely fixed: reachesDoc1 now contrasts role=admin against role=user through whatCanTargetAccess, so the assertion would fail if the server ignored context — and the helper null-guards the wire list.
Re-verified independently this round: all 17 GDrive expectations against the DSL, the 5 model constructor arg orders against their Lombok field orders, the 7 assertThrows against the exactly-6 getFgaUri call sites (check accounts for two), mapOf returns a mutable HashMap so the request.put("context", ...) paths in AuthzServiceImpl are safe, TestUtils.getClient() builds a fresh Client per call so setFgaCacheUri can't leak between tests, getInfo()/getMissingContext()/getConditions() are all impl-guaranteed non-null, and connection-refused surfaces as an IOException through @SneakyThrows so assertThrows(Exception.class, ...) catches it. Checkstyle doesn't scan test sources, so the 120-col limit is moot here anyway.
No issues sniffed out this round — nothing actionable survived verification. Good bones! 🦴
Woof!
Declared coverage: FULL — 1/1 changed files reviewed.
Declared coverage: FULL — 1/1 changed files reviewed.
yosiharan
left a comment
There was a problem hiding this comment.
Self review done, test covers ABAC and FGA Cache paths very nicely, ran manually to verify it passes when hitting a real env
e920006 to
76ca0cb
Compare
|
🐕 Review complete — View session on Shuni Portal 🐾 |
There was a problem hiding this comment.
🐕 Shuni's Review
Adds FGALiveTest — the GDrive schema round trip, ABAC context cases, dry-run, and the three-tier FGA cache-routing coverage, on the repo's existing TestUtils.getClient() + @RetryingTest harness. The previously reviewed commit was force-pushed away, so I re-reviewed the full file rather than a delta.
Traced this round: all 17 GDrive expectations against the DSL's can_create/can_edit chains (including the group#member userset on folder2) — all correct; the 7 assertThrows map onto exactly the 6 getFgaUri call sites, with the non-routed calls on the same client asserted to still succeed, which is what makes the negative tier meaningful; the 5 model constructor arg orders against their Lombok field orders; mapOf returns a mutable HashMap, so the request.put("context", …) paths are safe; TestUtils.getClient() builds a fresh Client per call, so setFgaCacheUri can't leak between tests; getInfo(), getMissingContext() and getConditions() are all impl-guaranteed non-null; and connection-refused reaches the caller as an IOException via @SneakyThrows, so assertThrows(Exception.class, …) catches it.
No issues sniffed out — nothing actionable survived verification. Good bones! 🦴 Woof!
Declared coverage: FULL — 1/1 changed files reviewed.
Declared coverage: FULL — 1/1 changed files reviewed.
76ca0cb to
6c8f85a
Compare
|
🐕 Review complete — View session on Shuni Portal 🐾 |
There was a problem hiding this comment.
Re-review after force-push — no actionable findings
The previously reviewed commit 76ca0cb is no longer reachable (force-pushed), so per the fallback I re-reviewed the full current PR diff instead of a delta. The result: the single changed file src/test/java/com/descope/sdk/mgmt/impl/FGALiveTest.java has the identical blob (f6c0a8d) as the version reviewed in the prior round — only the commits were rewritten (rebase onto the updated base). +315 lines, one new test file, no production code touched.
Because the base branch may have moved under the rebase, I re-verified the implementation assumptions this test depends on rather than trusting the earlier pass:
- Cache routing surface is still exactly 6
getFgaUricall sites —FGAServiceImplsaveSchema/createRelations/deleteRelations/check(both overloads share the site at :129) andAuthzServiceImplwhoCanAccess(:214) /whatCanTargetAccess(:255). The 7assertThrowsintestBadFgaCacheUrlFailsOnlyTheRoutedCallsmap onto those, and the 5 calls asserted to still succeed (loadSchema,dryRunSchema,saveResourcesDetails,loadResourcesDetails,resourceRelations) all still go through the non-routedgetUri. ManagementsBase.getFgaUristill normalizes withStringUtils.removeEnd(fgaCacheUri, "/"), so the deliberate trailing slash atFGALiveTest.java:230exercises the intended path.- Non-null guarantees the assertions rely on hold:
checkalways populatesinfoandinfo.missingContext(FGAServiceImpl.java:136-139), andloadSchemaalways setsconditionsbefore any early return (:72). - Model field orders still match every positional constructor call —
FGARelation(resource, resourceType, relation, target, targetType),FGACheckResult(allowed, relation, info),FGAResourceDetails(resourceId, resourceType, displayName),FGAResourceIdentifier(resourceId, resourceType),FGACheckInfo(direct, conditional, missingContext, …).Relation.getResource()used byreachesDoc1is still the resource id field. TestUtils.getClient()still returns a freshClient.builder()per call, sosetFgaCacheUriin the cache-tier tests cannot leak intofgaService/authzServicefrom@BeforeEach.EnvironmentUtils.getFgaCacheURL()/FGA_CACHE_URL_ENV_VARand theAuthzServicecontext overloads (whoCanAccess(4-arg),whatCanTargetAccess(2-arg)) all exist as called.
I also re-derived all 17 GDrive check expectations from the DSL independently (including the group1#member userset resolution for folder2 and the parent.owner chain giving u9 can_create/can_edit on folder1) — every expectation is correct, and expect()'s hardcoded folder/user types hold for all 17.
Correctness, security, error handling, and test-quality checks all pass. The shared-project trade-offs (no schema cleanup, ServerCommonException in onExceptions) are explicitly documented in the class javadoc and the inline comment at :97-98, so I'm not re-raising them.
Declared coverage: FULL — 1/1 changed files reviewed.
Mirrors integrationtests/tests/fga_test.go against a real project: the GDrive schema round trip with all its check expectations, the ABAC context cases (conditional allow and deny, missing context, condition on a permission), and loadSchema returning version and conditions. Adds coverage the Go suite does not have: dry-run, ABAC context through the authz queries, and FGA cache routing. Cache routing is covered three ways - pointing the cache URL at the API host (everything must keep working), pointing it at a dead port (only the six routed calls must fail, the rest must still succeed), and against a real cache when DESCOPE_FGA_CACHE_URL is set. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The server normalizes targetType on the tuple it echoes back from check, so compare the fields that identify the relation instead of the whole object. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
These tests replace the project's FGA schema, which is shared with the other live tests, so a schema-dependent call can hit a transient server error. Retry the same way the suite already retries rate limits. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Delete the schema once for the class instead of after every test, and fold the authz-context and loadSchema assertions into the ABAC test that already saves that schema. Halves the schema mutations per run, which is what was making concurrent CI runs fail each other's schema-dependent live tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Another live suite reads loadSchema().getName() without a null guard, so leaving the last schema in place is safer than deleting it, and it drops the remaining schema churn. Also assert the non-routed authz call does not throw rather than that its list is non-null, which the wire can legitimately omit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Drop the retry suspend to 10s so a deterministic failure does not idle for minutes across the JDK matrix, guard the deny-path whoCanAccess against a null list from the wire, and share one round-trip helper between the two cache tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Asserting non-null passed on an empty list, so it would have passed even if the context were ignored. Contrast admin and non-admin the way the whoCanAccess assertions above do. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
6c8f85a to
9e73bbb
Compare
|
🐕 Review complete — View session on Shuni Portal 🐾 |
There was a problem hiding this comment.
🐕 Shuni's Review
Adds FGALiveTest — live coverage for the FGA surface: the GDrive schema round trip with all 17 check expectations, ABAC context (including missingContext), dry-run, and three tiers of FGA cache-URL routing. One new test file, +315 lines, no production code touched.
Sniffed out 0 issues. Good bones! 🦴
The previously reviewed commit 6c8f85a was force-pushed away, so I reviewed the full current PR diff. Two things changed since the last round: the base is now origin/main (the three upstream PRs landed), and the file blob is unchanged (f6c0a8d). Since the base moved, I re-verified the implementation this test pins rather than trusting the earlier pass:
- Routing surface is still exactly 6
getFgaUrisites (FGAServiceImpl:50/:94/:107/:129,AuthzServiceImpl:214/:255), matching the 7assertThrows; the 5 calls asserted to survive a dead cache URL all still usegetUri. ManagementsBase.getFgaUristill trims the trailing slash, so the deliberate+ "/"at :230 exercises normalization;UriUtils.getUricomposes the leading slash correctly.checkstill guarantees non-nullinfoandmissingContext;loadSchemastill setsconditionsbefore every return path.- Positional model constructors still match field order (
FGARelation,FGACheckResult,FGAResourceDetails,FGAResourceIdentifier), andmapOfstill returns a mutable map for therequest.put("context", …)paths. TestUtils.getClient()still builds a freshClientper call and does not readDESCOPE_FGA_CACHE_URL(onlyConfigdoes), sosetFgaCacheUricannot leak into the@BeforeEachservices.@RetryingTest(onExceptions = …)is already used with the pinned junit-pioneer 1.9.1 inUserServiceImplTest.
I also re-derived all 17 GDrive expectations from the DSL independently — including the group1#member userset on folder2 and the parent.owner chain giving u9 can_create/can_edit on folder1 — all correct. The shared-project trade-offs (no schema cleanup, ServerCommonException retries) are documented in the class javadoc and at :97-98, so I'm not re-raising them. Woof!
Declared coverage: FULL — 1/1 changed files reviewed.
Related Issues
Verifies: https://github.com/descope/etc/issues/17574
Related PRs
Upstream PRs
In a Nutshell
integrationtests/tests/fga_test.goto the Java SDKmissingContextDescription
Adds
FGALiveTest, live coverage for everything the first three PRs added, in the harness the repo already uses (TestUtils.getClient()+@RetryingTeston rate limits, which CI runs with the project secrets).Ported from
integrationtests/tests/fga_test.go:runFGASchemaTest's GDrive schema, its 9 relations and all 17 check expectations, andTestFGAABACCheckWithContext's five assertions (conditional allow, conditional deny, missing context, and a condition on a permission). New on the Java side: dry-run, ABAC context throughwhoCanAccess/whatCanTargetAccess, andloadSchemareturning version and conditions.Cache routing gets three tiers, because CI cannot reach an authzcache instance:
getFgaUriincluding trailing-slash normalization.DESCOPE_FGA_CACHE_URLis set, skipped otherwise.Last of four stacked PRs — based on #349.
Must
Note for reviewers
Schemas are saved per-test case and not deleted to avoid clashes with concurrent running CI that all share the same test project ID.