Skip to content

Grants, windows and DPoP from dauth's new access tokens (#plan step 7) - #68

Open
elffjs wants to merge 4 commits into
mainfrom
org-host-step-7
Open

elffjs wants to merge 4 commits into
mainfrom
org-host-step-7

Conversation

@elffjs

@elffjs elffjs commented Sep 22, 2026

Copy link
Copy Markdown
Member

Step 7 of the did-directory org host plan, dq's share (spec §11.4). No backwards compatibility (spec §19 decision 17).

  • DQClaim embeds dauth's new tokenclaims.Token (cnf, grants[{subject, abilities, windows?, chain}]), validated on entry. Audience is TOKEN_AUDIENCE (default dq).
  • DPoP: every authenticated HTTP request needs a DPoP proof for its method and URL with ath over the token, matched to cnf.jkt (PUBLIC_BASE_URL gives the htu origin behind a proxy). Token accepted under the DPoP or Bearer scheme.
  • Windows: @requiresVehicleToken clamps from/to to the union of the subject's windows; nothing covered is refused, and a range straddling a gap is refused with the covered pieces named, so the caller splits it (the spec's merged segments are left for later). Privilege directives then check each ability over the range in scope, or at the current time for latest/snapshot/summary reads. Cloud-event after/before and the gRPC fetch bounds are clamped the same way.
  • Privileges → abilities: VEHICLE_NON_LOCATION_DATA → telemetry:read, VEHICLE_ALL_TIME_LOCATION → location:precise, VEHICLE_APPROXIMATE_LOCATION → location:approximate, VEHICLE_RAW_DATA → raw:read. VEHICLE_CURRENT_LOCATION, VEHICLE_COMMANDS and VEHICLE_VIN_CREDENTIAL leave the enum (unused in the schema; gqlgen forbids two values mapping to one string).
  • Deleted: the identity-api device-to-vehicle link and IDENTITY_API_URL; the requested subject must be a grant subject. The gRPC fetch port keeps bearer-only validation with raw:read; no DPoP there, the NetworkPolicy stays the compensating control.

Pins dauth at DIMO-Network/dauth#24's commit, whose go.mod requires the private did-directory module, so loading this module graph now needs GOPRIVATE/SSH access to it in CI.

🤖 Generated with Claude Code

https://claude.ai/code/session_011mDMpJffFJ4BmUyZPtb6j2

elffjs and others added 4 commits September 22, 2026 13:54
dq now checks the access tokens dauth's /exchange mints for the
delegation model (did-directory plan §6 step 7, spec §11.4). No backwards
compatibility (spec §19 decision 17).

DQClaim embeds the new tokenclaims.Token and is validated on the way in;
the audience is TOKEN_AUDIENCE, default dq. Every authenticated HTTP
request must carry a DPoP proof for its method and URL with ath over the
token, signed by the key cnf.jkt names (PUBLIC_BASE_URL gives the htu
origin behind a proxy).

@requiresVehicleToken finds the grants for the query's subject and, on a
field with from/to, clamps the range to the union of the subject's
windows: nothing covered is refused, and a range that straddles a gap is
refused naming the covered pieces so the caller splits the query (the
spec asks for merged segments; v1 refuses rather than interpolates). The
privilege directives check each required ability for the subject in
scope over the range in scope, or at the current time when there is no
range. The Privilege enum keeps model-garage's names and maps to
abilities; VEHICLE_CURRENT_LOCATION, VEHICLE_COMMANDS and
VEHICLE_VIN_CREDENTIAL leave the enum because gqlgen forbids two values
sharing one string. Cloud-event reads take raw:read with after/before
clamped the same way. The gRPC fetch port keeps bearer validation, takes
raw:read over each requested subject and clamps its bounds; it does not
check DPoP, with the NetworkPolicy as the compensating control.

Deleted: the identity-api device-to-vehicle link and IDENTITY_API_URL;
the requested subject must be a grant subject.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011mDMpJffFJ4BmUyZPtb6j2
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011mDMpJffFJ4BmUyZPtb6j2
Writes dimo.status events carrying a speed signal into lake.raw_events in
din's shape and decodes them once, so dq boots over a catalog that already
has signals. did-directory's scripts/demo.sh uses it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- @requiresVehicleToken puts the subject's windows in the request context
  (internal/coverage) and refuses a token with no data window for the
  subject; a commands-only token reads no data.
- The privilege directives clamp a field's own range before checking it,
  so on events, segments and dailyActivity (where gqlgen runs them before
  the vehicle check) a wide range is clamped rather than refused.
- signalsLatest and signalsSnapshot drop readings outside the windows;
  dataSummary is refused unless the windows cover all time.
- segments reports a trip already under way from the window's start and
  summarises it from there; dailyActivity clips its days to the window;
  location gap-fill never reads before the window's start.
- ListCloudEventsFromIndex checks the fetched events' times against the
  windows, since the index header is the caller's to write.
- Bumps dauth to the commit whose token validation requires exp, cnf.jkt
  and windows on historical grants.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant