Skip to content

refactor: replace CheckAccess with assertScope() — delete 250-line hardcoded scope map#26

Closed
herpaderpaldent wants to merge 8 commits into
feat/esi-rate-limit-overhaulfrom
refactor/assert-scope
Closed

refactor: replace CheckAccess with assertScope() — delete 250-line hardcoded scope map#26
herpaderpaldent wants to merge 8 commits into
feat/esi-rate-limit-overhaulfrom
refactor/assert-scope

Conversation

@herpaderpaldent
Copy link
Copy Markdown
Contributor

Summary

Replaces the 250-line hardcoded CheckAccess.php scope map with assertScope() — a method on EsiTransportInterface that lets each generated operation class enforce its own scope requirement.

Changes

  • Delete CheckAccess.php — 250 lines of (method, path) → scope maintenance burden gone
  • Delete EsiScopeAccessDeniedException.php — superseded by ScopeAccessDeniedException from seatplus/esi-schema
  • EsiClient::assertScope(?string $scope) — checks JWT scopes; null = public endpoint (no-op)
  • Remove hasAccess() pre-flight from invoke() — check now lives in each execute() call
  • Bump seatplus/esi-schema^1.1 — requires the assertScope() interface addition
  • Remove /latest/ URL prefix — ESI OpenAPI 3.1 paths have no version segment
  • Default compatibility_date to '2025-12-16' — correct versioning header sent automatically
  • Lower PHP requirement to ^8.3
  • Clean up formats.yml

Why

Each of the 208 generated operation classes already knows REQUIRED_SCOPE. Having a second parallel map in CheckAccess was a maintenance liability (any new/changed endpoint required manual updates in two places).

Test coverage

All 113 tests pass. esi-schema 1.1.0 ships 209 tests verifying assertScope() is called on all 208 operation classes.

herpaderpaldent and others added 8 commits May 15, 2026 06:49
…erface

Scope enforcement now lives where scope is defined. Each generated execute()
calls $transport->assertScope(self::REQUIRED_SCOPE) before any HTTP call.
The transport (EsiClient) implements the check against the JWT token.

Changes:
- EsiClient: implement assertScope(?string $scope): void
  - null = public endpoint → no-op
  - non-null = must be present in JWT scopes → ScopeAccessDeniedException
- EsiClient: remove CheckAccess wiring from constructor and withToken()
- EsiClient: remove hasAccess() pre-flight from invoke()
- EsiScopeAccessDeniedException: now extends ScopeAccessDeniedException
  from esi-schema for backward compatibility
- Delete CheckAccess.php (250-line hardcoded scope map — no longer needed)
- Delete CheckAccessTest.php (replaced by assertScope tests in EsiClientTest)
- Bump seatplus/esi-schema: ^1.1 (requires assertScope in EsiTransportInterface)
- Update GeneratedResourcesTest: use real JWT tokens, remove CheckAccess mock
- Update EsiClientTest: replace access-denied test with assertScope tests

Requires seatplus/esi-schema ^1.1 (PR #4).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Until esi-schema PR #4 is merged and 1.1.0 tagged on Packagist,
use the branch dev alias so CI can resolve the dependency.

Will be reverted to ^1.1 once tag exists.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…formats workflow

- Add docblock to EsiClient::assertScope() explaining null semantics
- Update formats.yml to also trigger on composer.json changes and
  pull_request targeting feat/esi-rate-limit-overhaul

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… sufficient

Explicit dev-* constraints override minimum-stability per-package, so
setting minimum-stability=dev globally was unnecessary and caused
pest-plugin-type-coverage to resolve a dev build instead of stable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…gist)

Replaces the temporary dev-feat/assert-scope alias now that esi-schema
PR #4 has been merged and tagged 1.1.0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ption from esi-schema directly

No backwards compatibility needed. Callers should catch
Seatplus\EsiSchema\Contracts\ScopeAccessDeniedException.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… spec

The ESI OpenAPI 3.1 spec (esi.evetech.net/meta/openapi.yaml) defines:
  servers: [url: https://esi.evetech.net]
  paths:  /alliances, /characters/{character_id}/assets, …

No version prefix anywhere. Versioning is handled by X-Compatibility-Date
header (already sent by GuzzleFetcher). The /latest/ prefix was a Swagger 2.0
basePath artifact.

Changes:
- buildDataUri(): /{path}/ instead of /latest/{path}/
- EsiConfiguration: default compatibility_date to '2025-12-16'
  (matches esi-schema generation date; update when regenerating)
- Update tests accordingly

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@herpaderpaldent
Copy link
Copy Markdown
Contributor Author

Changes merged directly into feat/esi-rate-limit-overhaul (PR #22).

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