diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..3d228b9 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,22 @@ +# AGENTS + +This repository packages an Elixir library for building LTI 1.3 Tool and Platform integrations. + +## Table Of Contents + +- `README.md`: public usage guide, installation, and end-to-end examples for tool and platform flows. +- `ARCHITECTURE.md`: system map for the library modules, pluggable providers, and key management flow. +- `docs/STACK.md`: language, runtime, and dependency baseline for the library. +- `docs/TOOLING.md`: day-to-day commands, formatting, compile, and publish workflow. +- `docs/TESTING.md`: ExUnit test layout, mocks, and required verification gates. +- `docs/OPERATIONS.md`: operational expectations for a library release, observability limits, and performance notes. +- `docs/FRONTEND.md`: guidance for example consumer UIs; the library itself does not ship a frontend. +- `docs/PRODUCT_SENSE.md`: product intent and repository-level assumptions. +- `docs/BACKEND.md`: backend boundaries for library consumers and core modules. +- `docs/SECURITY.md`: security-sensitive areas around keys, JWT validation, nonce handling, and LTI handshake data. + +## Working Notes + +- Treat this repository as a reusable package, not a deployable service. +- Prefer facts grounded in `README.md`, `mix.exs`, `config/*.exs`, `docs/*.md`, and GitHub workflows over assumptions. +- There is already a user change in `mix.exs`; do not overwrite it unless explicitly asked. diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..829fe8c --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,25 @@ +# Architecture + +## System Map + +`lti_1p3` is an Elixir library that exposes two main integration surfaces: + +- Tool-side modules under `Lti_1p3.Tool` for registration, deployment, OIDC login, launch validation, and service calls such as AGS and NRPS. +- Platform-side modules under `Lti_1p3.Platform` for platform instance management, login hints, and authorization redirect flow. + +Shared concerns live in the root `Lti_1p3` namespace and supporting modules: + +- Claim parsing modules under `lib/lti_1p3/claims/` normalize LTI claim payloads. +- Role helpers under `lib/lti_1p3/roles/` encapsulate role parsing and semantics. +- `Lti_1p3.DataProvider` defines the persistence boundary. The default configured provider in test is the in-memory provider, but the library is intended to support durable custom providers. +- `Lti_1p3.KeyProvider` and the key provider supervisor manage remote platform JWK fetching, caching, and refresh behavior for JWT verification. +- `Lti_1p3.KeyGenerator`, `Lti_1p3.Jwk`, `Lti_1p3.Nonce`, and related modules handle key material, public key exposure, and replay protection primitives. + +The repository is documentation-heavy because many consumers integrate the library into Phoenix or other Elixir applications. The library itself does not own application routes, controllers, HTML, or persistent storage; those are expected to be supplied by integrators. + +## Major Boundaries + +- Public package API: `Lti_1p3`, `Lti_1p3.Tool`, and `Lti_1p3.Platform`. +- Persistence boundary: custom data providers and registrations/deployments storage are outside the library core. +- Runtime integration boundary: application supervision trees must add the key provider supervisor when using version `1.0+`. +- Network boundary: outbound HTTP is used for remote JWK retrieval and service APIs; tests replace HTTP with a mock client. diff --git a/docs/BACKEND.md b/docs/BACKEND.md new file mode 100644 index 0000000..38705a7 --- /dev/null +++ b/docs/BACKEND.md @@ -0,0 +1,17 @@ +# Backend + +## Service Architecture + +This repository is a backend library. Core responsibilities are: + +- construct and validate LTI 1.3 requests and responses +- manage platform and tool metadata structures +- parse claims and roles +- integrate with pluggable persistence and key providers +- call AGS and NRPS service endpoints + +## Backend Boundaries + +- No owned web server, router, controller, or HTML rendering layer +- No first-party durable database implementation in this repository +- No background job system beyond what consumers wire into their supervision tree diff --git a/docs/CODEREVIEW.md b/docs/CODEREVIEW.md new file mode 100644 index 0000000..53d80c4 --- /dev/null +++ b/docs/CODEREVIEW.md @@ -0,0 +1,17 @@ +# Code Review + +## Policy + +Review changes as library changes first, application changes second. Prioritize: + +- API compatibility for public modules and structs +- Security regressions in login, launch validation, nonce handling, and key retrieval +- Incorrect assumptions about provider behavior or storage semantics +- Documentation drift in `README.md` and `docs/*.md` when setup or flows change + +## Review Guides + +- Check whether tests cover changed public behavior +- Check whether `mix compile --warnings-as-errors` and `mix test` still pass +- Check whether example snippets remain aligned with the actual API +- Check whether network, cache, or cryptographic behavior changed without explicit rationale diff --git a/docs/DESIGN.md b/docs/DESIGN.md new file mode 100644 index 0000000..1d973d8 --- /dev/null +++ b/docs/DESIGN.md @@ -0,0 +1,8 @@ +# Design + +## Principles + +- Favor explicit module boundaries that map to LTI concepts such as tool, platform, claims, roles, and services +- Keep host-application concerns pluggable instead of baking in Phoenix or Ecto dependencies +- Document integration flows with executable-looking examples so consumers can wire the library correctly +- Protect correctness and security in handshake code before optimizing ergonomics diff --git a/docs/FRONTEND.md b/docs/FRONTEND.md new file mode 100644 index 0000000..6537233 --- /dev/null +++ b/docs/FRONTEND.md @@ -0,0 +1,11 @@ +# Frontend + +## UI Rules + +This repository does not ship a frontend application. Existing UI guidance in `README.md` is limited to example Phoenix controllers, routes, and HTML forms that demonstrate the LTI login and launch handshake. + +When adding example UI material: + +- Keep examples framework-appropriate for Elixir consumers, especially Phoenix +- Treat HTML and controller snippets as documentation artifacts, not a supported UI layer +- Avoid introducing a repo-local JavaScript frontend unless the package scope changes explicitly diff --git a/docs/ISSUE_TRACKING.md b/docs/ISSUE_TRACKING.md new file mode 100644 index 0000000..9378ed4 --- /dev/null +++ b/docs/ISSUE_TRACKING.md @@ -0,0 +1,12 @@ +# Issue Tracking + +## System Of Record + +No repository-local issue tracker configuration is defined in the harness contract today. In practice, maintenance work should follow the upstream GitHub repository workflow because CI and package publishing already run through GitHub. + +## Intake Workflow + +- Reproduce the problem with a focused ExUnit test when possible +- Classify whether the change affects tool flow, platform flow, shared claims/roles, provider boundaries, or docs only +- Record any external compatibility constraints such as LTI spec behavior or Hex package expectations +- Prefer small, reviewable changes that keep docs and tests in sync diff --git a/docs/OPERATIONS.md b/docs/OPERATIONS.md new file mode 100644 index 0000000..8bd6a05 --- /dev/null +++ b/docs/OPERATIONS.md @@ -0,0 +1,30 @@ +# Operations + +## Observability + +This repository is a library, so it does not own production telemetry pipelines or dashboards. Observability is mainly: + +- CI signal from GitHub Actions build and test workflows +- Coverage reporting through Coveralls +- Consumer-application logs emitted through the standard Elixir logger + +Changes that affect runtime behavior should preserve useful error tuples and logger compatibility for downstream applications. + +## Performance + +Performance-sensitive paths are concentrated around: + +- JWT validation during launch flow +- JWK retrieval, caching, and refresh behavior +- AGS and NRPS service request handling + +Prefer avoiding repeated network fetches, unnecessary JSON re-parsing, and regressions in hot-path validation code. Key provider cache behavior is a primary performance lever in this codebase. + +## Rollout + +Releases are package-oriented rather than service-oriented: + +- CI validates pushes and pull requests on `master` +- Hex publishing is triggered by version tags matching the publish workflow +- Library changes that alter integration setup must update `README.md` and related docs before release +- There is no runtime rollout plan in this repository; consumer applications own deployment and migration sequencing diff --git a/docs/PLANS.md b/docs/PLANS.md new file mode 100644 index 0000000..85587dc --- /dev/null +++ b/docs/PLANS.md @@ -0,0 +1,5 @@ +# Plans + +## Work Item Model + +Active work lives under `docs/exec-plans/current/`. diff --git a/docs/PRODUCT_SENSE.md b/docs/PRODUCT_SENSE.md new file mode 100644 index 0000000..367e08d --- /dev/null +++ b/docs/PRODUCT_SENSE.md @@ -0,0 +1,14 @@ +# Product Sense + +## Product Goals + +- Provide a reusable Elixir implementation of the LTI 1.3 specification for both Tool and Platform integrations +- Keep the library flexible enough for different host applications by making persistence pluggable +- Reduce integration complexity by supplying clear examples, claim parsing helpers, and service abstractions +- Preserve interoperability and security expectations around OIDC login, JWT validation, keys, deployments, and nonces + +## Assumptions + +- Most users integrate this package into a Phoenix or Elixir web application rather than use it standalone +- Good package documentation is part of the product surface, not a secondary concern +- Backward-compatible API changes and secure defaults matter more than adding framework-specific convenience layers diff --git a/docs/QUALITY_SCORE.md b/docs/QUALITY_SCORE.md new file mode 100644 index 0000000..6a958b1 --- /dev/null +++ b/docs/QUALITY_SCORE.md @@ -0,0 +1,12 @@ +# Quality Score + +## Current State + +Baseline quality signals are present: + +- automated build/test workflow in GitHub Actions +- package documentation through ExDoc +- coverage support through ExCoveralls and Coveralls +- broad test coverage across tool, platform, roles, providers, and key management paths + +The main quality risk is drift between public docs/examples and the actual library API. diff --git a/docs/RELIABILITY.md b/docs/RELIABILITY.md new file mode 100644 index 0000000..615a024 --- /dev/null +++ b/docs/RELIABILITY.md @@ -0,0 +1,8 @@ +# Reliability + +## Expectations + +- Launch validation should fail deterministically with structured errors +- Key retrieval should prefer cached data and degrade gracefully when refresh fails +- In-memory defaults are suitable for examples and tests, not for durable production storage +- Changes that affect registration, deployment, or nonce behavior need regression coverage diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 0000000..b1d5d8d --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,9 @@ +# Security + +## Requirements + +- Never expose private keys in docs, examples, or code paths meant for consumers +- Preserve nonce, state, issuer, audience, and deployment validation behavior +- Treat remote JWK fetching and cache invalidation as security-sensitive code +- Maintain clear separation between public JWK exposure and private key storage +- Review any claim parsing change for spoofing, replay, or authorization implications diff --git a/docs/STACK.md b/docs/STACK.md new file mode 100644 index 0000000..8099d36 --- /dev/null +++ b/docs/STACK.md @@ -0,0 +1,25 @@ +# Stack + +## Languages + +- Elixir `~> 1.17` in `mix.exs` +- Erlang/OTP `27.0.1` and Elixir `1.17.2-otp-27` in `.tool-versions` +- Markdown for user and maintainer documentation +- YAML for harness metadata + +## Frameworks + +- Mix for build, test, docs, and packaging workflows +- ExUnit for tests +- ExCoveralls for coverage reporting +- ExDoc for package documentation +- Joken for JWT handling +- HTTPoison for HTTP interactions with remote services and JWK endpoints +- Jason for JSON encoding/decoding +- Timex and UUID as supporting libraries + +## Storage + +- Library core is storage-agnostic through the `Lti_1p3.DataProvider` behavior +- Default examples and tests use `Lti_1p3.DataProviders.MemoryProvider` +- `docker-compose.yml` provides PostgreSQL for local work that needs a durable provider or integration experimentation, but no database-backed provider lives in this repository diff --git a/docs/TESTING.md b/docs/TESTING.md new file mode 100644 index 0000000..8d40771 --- /dev/null +++ b/docs/TESTING.md @@ -0,0 +1,16 @@ +# Testing + +## Test Types + +- Unit tests for core library modules under `test/lti_1p3/**` +- Behavior and integration-style tests for launch validation, key provider supervision, AGS, NRPS, and platform flows +- Support helpers under `test/support/**` +- HTTP interactions are mocked in test via `Lti_1p3.Test.MockHTTPoison` configured in `config/test.exs` +- Tests run with `ExUnit.start(exclude: [:skip])` and logger backends disabled to keep output focused + +## Required Gates + +- `mix test` +- `mix compile --warnings-as-errors` for code paths touched by the change +- `mix test.coverage` when a change materially affects public flows or security-sensitive behavior +- Add or update tests when changing launch validation, claim parsing, key caching, or service integrations diff --git a/docs/TOOLING.md b/docs/TOOLING.md new file mode 100644 index 0000000..0113248 --- /dev/null +++ b/docs/TOOLING.md @@ -0,0 +1,21 @@ +# Tooling + +## Commands + +- `mix deps.get`: install dependencies +- `mix compile`: compile the library +- `mix compile --warnings-as-errors`: strict compile gate used in CI +- `mix test`: run the ExUnit suite +- `mix test.coverage`: generate HTML coverage via ExCoveralls +- `mix format`: format Elixir sources using `.formatter.exs` +- `mix docs`: generate ExDoc output +- `mix hex.build`: build the Hex package +- `mix hex.publish --yes`: publish a tagged release from CI + +## Required Gates + +- Format cleanly with `mix format` +- Compile successfully, ideally with `mix compile --warnings-as-errors` +- Pass `mix test` +- Keep public docs coherent when APIs or setup guidance change +- For release work, ensure the tag-based publish workflow remains valid diff --git a/docs/design-docs/core-beliefs.md b/docs/design-docs/core-beliefs.md new file mode 100644 index 0000000..bc6e15b --- /dev/null +++ b/docs/design-docs/core-beliefs.md @@ -0,0 +1,5 @@ +# Core Beliefs + +- The library should remain framework-light so host applications can choose their own persistence, supervision, and web layers. +- LTI handshake correctness and security outrank convenience APIs. +- Examples and documentation are part of the product surface because most users learn the package from repository docs. diff --git a/docs/design-docs/index.md b/docs/design-docs/index.md new file mode 100644 index 0000000..672d83b --- /dev/null +++ b/docs/design-docs/index.md @@ -0,0 +1,7 @@ +# Design Docs Index + +Use `docs/design-docs/` for deeper slice-level design notes when implementation work exceeds what belongs in `ARCHITECTURE.md`. + +Current seed documents: + +- `core-beliefs.md`: durable design assumptions for the library diff --git a/docs/exec-plans/tech-debt-tracker.md b/docs/exec-plans/tech-debt-tracker.md new file mode 100644 index 0000000..ee8a49c --- /dev/null +++ b/docs/exec-plans/tech-debt-tracker.md @@ -0,0 +1,4 @@ +# Tech Debt Tracker + +- Track future work here when package internals, docs, or release workflow need cleanup outside a specific feature plan. +- Current notable debt signal: repository docs must stay aligned with the version `1.0+` key provider supervision requirement. diff --git a/docs/generated/db-schema.md b/docs/generated/db-schema.md new file mode 100644 index 0000000..3c2d6e0 --- /dev/null +++ b/docs/generated/db-schema.md @@ -0,0 +1,5 @@ +# Database Schema + +This repository does not define a canonical database schema. + +Persistence is delegated to implementations of the `Lti_1p3.DataProvider` behavior. If a future work item introduces an official durable provider in this repository, record its schema here. diff --git a/docs/product-specs/index.md b/docs/product-specs/index.md new file mode 100644 index 0000000..036ae98 --- /dev/null +++ b/docs/product-specs/index.md @@ -0,0 +1,5 @@ +# Product Specs Index + +Use this directory for work-item or feature-level product specs when repository maintenance expands beyond routine library fixes. + +There are no active product specs checked in yet. diff --git a/harness.yml b/harness.yml new file mode 100644 index 0000000..f3458a9 --- /dev/null +++ b/harness.yml @@ -0,0 +1,36 @@ +version: 1 + +capabilities: + feature_flags: + adoption: disabled + default: exclude + details_file: docs/OPERATIONS.md + telemetry: + adoption: enabled + default: include + details_file: docs/OPERATIONS.md + performance_requirements: + adoption: enabled + default: exclude + details_file: docs/OPERATIONS.md + code_review: + adoption: enabled + default: include + details_file: docs/CODEREVIEW.md + issue_tracking: + adoption: enabled + default: include + details_file: docs/ISSUE_TRACKING.md + +providers: + observability: + name: none + issue_tracker: + name: none + +links: + architecture: ARCHITECTURE.md + stack: docs/STACK.md + tooling: docs/TOOLING.md + testing: docs/TESTING.md + operations: docs/OPERATIONS.md