FR-26219 Namespace every SpiceDB read to the resolved instance - #81
Open
dianaKhortiuk-frontegg wants to merge 4 commits into
Open
FR-26219 Namespace every SpiceDB read to the resolved instance#81dianaKhortiuk-frontegg wants to merge 4 commits into
dianaKhortiuk-frontegg wants to merge 4 commits into
Conversation
dianaKhortiuk-frontegg
force-pushed
the
fr-26219-sdk-scoping
branch
from
September 9, 2026 11:45
e4a057e to
d5758d1
Compare
dianaKhortiuk-frontegg
force-pushed
the
fr-26219-sdk-namespaced-reads
branch
2 times, most recently
from
September 9, 2026 11:51
2f347e5 to
a147ef4
Compare
This was referenced Sep 9, 2026
dianaKhortiuk-frontegg
force-pushed
the
fr-26219-sdk-namespaced-reads
branch
2 times, most recently
from
September 9, 2026 15:00
6c013ab to
fdbd6f4
Compare
Applies the model from the previous PR to every read path. This is the PR that changes existing behaviour, so it is the one to read for regressions. The client resolves the instance before the try block, so a resolution failure throws rather than degrading into the fallback boolean — a fallback would be answering a question scoped to no instance at all. The resolved namespace is threaded through all four query strategies, both lookup builders and the batch feature path; the route cache key is now per prefix, where it previously held every vendor's routes under one key. New public surface: instanceId as a trailing options argument on all five methods, readSchemaFor(instanceId), and per-instance fallback config. Raw spiceClient is marked @deprecated. Log lines carry instanceId. With no instances configured every request resolves to a legacy namespace and the built gRPC requests are byte-identical to master. 253 tests, tsc clean, 0 lint errors.
InvalidObjectTypeException extends Error, not ConfigurationInputIsInvalidException, so the rethrow guards did not cover it and a caller passing another instance's prefix — v_other/document — was answered with the fallback boolean instead of an error. That is the behaviour d05162d exists to prevent. Single calls throw, which is what isEntitledTo should do for a caller-input error. Batches fail per item instead: rethrowing inside the Promise.all made one bad entityType discard every other result, so the offending item now carries `error` while its neighbours answer normally. `result` is left undefined rather than false, so nothing is granted and a caller can tell a refusal from a denial. EntitlementsResult gains an optional `error`, which is additive for consumers. Verified against an unreachable endpoint, so SpiceDB is never consulted: before, isEntitledTo resolved to {"result":false}; now it throws. A three-item batch with one bad entityType returns true / error / true.
The block splitter counted every brace in a line, including braces inside
string literals and comments. A caveat body containing x == "{" left the block
open, so everything after it was returned as part of that instance:
definition v_aaa/user {}
caveat v_aaa/c(x string) { x == "{" }
definition v_bbb/secret {}
readSchemaFor('a') -> "... definition v_bbb/secret {}"
SpiceDB v1.53.0 accepts that schema, so it was reachable, and it defeats the
reason readSchemaFor exists. Braces are now counted only outside single and
double quoted strings, line comments and block comments, with escapes handled.
A block-comment line is also no longer mistaken for a block header.
Six cases pinned in spicedb-entitlements.client.read-schema.spec.ts, including
that the instance's own caveat body still comes back intact.
BREAKING CHANGE: spiceClient is no longer public. Direct access bypasses instance namespacing and can read another instance's data. Use isEntitledTo, the lookup methods, or readSchemaFor with an instanceId instead. The field carried @deprecated in an earlier revision of this branch. A private field cannot be deprecated for callers who can no longer reach it, so the note goes with it.
dianaKhortiuk-frontegg
force-pushed
the
fr-26219-sdk-namespaced-reads
branch
from
September 10, 2026 11:21
370be48 to
ed92678
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Applies the instance model to every SpiceDB read. The only PR in the stack that changes behaviour.
+1384against #78 — source+340across 10 files, tests+1044.Spec
namespace.type()on all seven query paths; a caller type containing/is rejected on both FGA sides and both lookup builders; route cache keyed per namespace.instanceIdon every public method, per-instance fallback,readSchemaFor.spiceClientbecomes private rather than public-and-@deprecatedas the spec says: direct access bypasses namespacing entirely, so this is a breaking change and takes the release semver-major.InstanceResolutionExceptionrethrown ahead of the fallback catch-all, so an unresolved instance throws instead of answeringfalse.Notes
instanceIdis a secondoptionsargument, not a request field as spec'd.lookup-response.mapper.tsuntouched — nothing to strip. It echoes the caller's own type and only decodes ids, so no prefix can reach a response.instanceId. Equivalent, now that duplicate prefixes throw at boot.instanceIdon the three lookup log lines.Base #78