Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pnpm build

## HTTP runtime tests

`pnpm test:http` runs the suites in `api/tests/http` against the activity, badge-definition, badge-query, EVM-link, acknowledgement, collection, context-measurement, context attachment and evaluation, contributor-information, funding, location, profile, organization, feature, work-scope-tag, vocabulary-tag, graph, and contribution query XRPC endpoints installed from this checkout. These tests exercise real HTTP behavior against PostgreSQL, not only Lua handlers with a fake database.
`pnpm test:http` runs the suites in `api/tests/http` against the activity, badge-definition, badge-query, EVM-link, acknowledgement, collection, context-measurement, context attachment and evaluation, contributor-information, funding, location, profile, organization, feature, work-scope-tag, rights, vocabulary-tag, graph, and contribution query XRPC endpoints installed from this checkout. These tests exercise real HTTP behavior against PostgreSQL, not only Lua handlers with a fake database.

The local runner requires a local Docker Compose daemon, `psql`, and the pinned PostgreSQL and HappyView images already cached locally. Set `PSQL_PATH` to the absolute path of a trusted `psql` executable:

Expand All @@ -31,8 +31,9 @@ The bridge network permits container egress. HappyView receives loopback placeho

The HTTP gate fails if it discovers no suites, executes no `node:test` cases, or runs only skipped cases. Current coverage includes:

- Funding record retrieval, repeated filters, and pagination.
- Funding record retrieval, repeated filters, publisher-sidecar hydration, and pagination.
- Badge-definition retrieval with an icon and allowed-issuer list, publisher-sidecar hydration, author and badge-type filters, `createdAt`/URI pagination ties, and named error responses.
- Rights record retrieval and author-filtered listing, nullable publisher sidecars, repeated-author OR filtering, and stable `createdAt`/URI cursor pagination.
- EVM-link lookup and listing, actor/address filters, `createdAt`/URI pagination ties in both directions, nullable sidecar hydration, and named error responses.
- Feature-query coverage in `api/tests/http/features.http.test.js` exercises exact retrieval and hydrated or absent author sidecars, author/type and organization-presence filters, bidirectional `createdAt`/URI pagination ties, and named request errors.
- Contributor-information retrieval by exact AT-URI and listing with repeated-author filters, cursor pagination, hydrated and missing author sidecars, and named runtime errors.
Expand All @@ -47,7 +48,7 @@ The HTTP gate fails if it discovers no suites, executes no `node:test` cases, or
- Collection retrieval with CBOR-derived CIDs, location/tag projections, author, organization, item and tag filters, title/shortDescription search, `createdAt`/URI pagination ties, and source-order item pagination with exact-version resolution.
- Graph actor/entity lookups and lists, tied-key pagination, nullable profile/organization sidecars, entity target resolution, and the global recent-follows `before` filter.
- Contribution exact-record retrieval, repeated publisher filters, tied ascending/descending cursor pagination, nullable publisher sidecars, and named errors.
- Badge and contribution fixtures with CBOR-derived record CIDs; contribution DIDs are distinct from baseline fixture identities.
- Badge, badge-query, acknowledgement, contribution, and rights HTTP fixtures with CBOR-derived record CIDs; contribution DIDs are distinct from baseline fixture identities.
- Location retrieval with nullable sidecars, repeated author/URI/location-type filters, unsupported-search errors, tied pagination in both directions, malformed/absent `createdAt` handling, and named errors.
- HTTP fixtures for activity, collection, funding, badge-definition, badge-query, EVM-link, acknowledgement, feature, work-scope-tag, contribution, contributor-information, actor, context-measurement, context attachment and evaluation, graph, location, measurement, and vocabulary-tag records use CBOR-derived CIDs.

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ This checkout is one of the additive local sibling branches used to compose the

Included query endpoints:

- Rights: `org.hypercerts.claim.getRights`, `org.hypercerts.claim.listRights`

- Badge definitions: `app.certified.badge.getBadgeDefinition`, `app.certified.badge.listBadgeDefinitions`
- Badge queries: `app.certified.badge.searchBadgeDefinitions`, `app.certified.badge.getBadgeAward`, `app.certified.badge.listBadgeAwards`, `app.certified.badge.getBadgeResponse`, `app.certified.badge.listBadgeResponses`
- Certified EVM links: `app.certified.link.getEvmLink`, `app.certified.link.listEvmLinks`
Expand All @@ -17,6 +19,8 @@ Included query endpoints:

`api/manifest.json` is authoritative for the modules and validation Lexicons included in this checkout. The `docs/` workspace contains the endpoint explorer and full schema snapshots.

## Checks

```sh
pnpm install --frozen-lockfile
pnpm check
Expand All @@ -31,6 +35,7 @@ pnpm build

| Capability | XRPC endpoints | HTTP contracts |
| --- | --- | --- |
| Rights | `org.hypercerts.claim.getRights`, `org.hypercerts.claim.listRights` | Exact retrieval, author filters, nullable sidecars, stable pagination, and named errors |
| Funding receipts | `org.hypercerts.funding.getReceipt`, `org.hypercerts.funding.listReceipts` | Record retrieval, repeated filters, stable pagination, and named runtime errors |
| Badge definitions | `app.certified.badge.getBadgeDefinition`, `app.certified.badge.listBadgeDefinitions` | Record/CID retrieval, publisher sidecars, filters, tied pagination, and named runtime errors |
| Badge queries | `app.certified.badge.searchBadgeDefinitions`, `app.certified.badge.getBadgeAward`, `app.certified.badge.listBadgeAwards`, `app.certified.badge.getBadgeResponse`, `app.certified.badge.listBadgeResponses` | Baseline-aware definition search, exact-version award/response lookups, recipient status, raw response history, filters, and cursor pagination |
Expand Down
14 changes: 12 additions & 2 deletions api/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# HappyView API toolkit and query modules

This package owns the shared API installer and build tooling, pinned upstream Lexicons, common view definitions, reusable Lua projections, offline fixture/test utilities, and the EVM-link, feature, contribution, badge-query, vocabulary-tag, and acknowledgement modules. The `modules/shared/manifest.json` contains record schemas and shared query/view Lexicons; it contains no Lua endpoint scripts. A foundation-only install does not implement those queries. Capability modules listed in the root manifest register their endpoint Lexicons and Lua handlers separately; the `badge-queries` module installs five public badge query Lexicons and their Lua handlers.
This package owns the shared API installer and build tooling, pinned upstream Lexicons, common view definitions, reusable Lua projections, offline fixture/test utilities, and the EVM-link, feature, contribution, rights, badge-query, vocabulary-tag, and acknowledgement modules. The `modules/shared/manifest.json` contains record schemas and shared query/view Lexicons; it contains no Lua endpoint scripts. A foundation-only install does not implement those queries. Capability modules listed in the root manifest register their endpoint Lexicons and Lua handlers separately; the `badge-queries` module installs five public badge query Lexicons and their Lua handlers.

## EVM-link queries

Expand Down Expand Up @@ -28,7 +28,7 @@ PSQL_PATH="$(command -v psql)" pnpm test:http

## HTTP runtime tests

HTTP suites live in `api/tests/http` and exercise the funding, badge-definition, badge-query, EVM-link, feature, work-scope-tag, contribution, context-measurement, profile, organization, context attachment and evaluation, activity, collection, acknowledgement, vocabulary-tag, graph, and location XRPC endpoints installed from the current checkout. `pnpm test:http` discovers `*.http.test.js` suites and fixture modules named `*.fixture.js`, then creates a random Compose project with loopback-only dynamic ports, PostgreSQL data on tmpfs, and a task-owned default bridge network. Bridge networking permits container egress. HappyView receives loopback placeholder upstream URLs and proxy variables pointing to `127.0.0.1:9`; these are application-level settings, not network-hard egress isolation. The installer and HTTP suites target only the task-owned loopback service. The runner installs this checkout's manifest, seeds shared and HTTP fixtures, runs the suites, and tears down only that generated Compose project and its temporary credentials. Locally, Compose uses `--pull never`; missing cached images fail before service startup.
HTTP suites live in `api/tests/http` and exercise the funding, badge-definition, badge-query, EVM-link, feature, work-scope-tag, contribution, rights, context-measurement, profile, organization, context attachment and evaluation, activity, collection, acknowledgement, vocabulary-tag, graph, and location XRPC endpoints installed from the current checkout. `pnpm test:http` discovers `*.http.test.js` suites and fixture modules named `*.fixture.js`, then creates a random Compose project with loopback-only dynamic ports, PostgreSQL data on tmpfs, and a task-owned default bridge network. Bridge networking permits container egress. HappyView receives loopback placeholder upstream URLs and proxy variables pointing to `127.0.0.1:9`; these are application-level settings, not network-hard egress isolation. The installer and HTTP suites target only the task-owned loopback service. The runner installs this checkout's manifest, seeds shared and HTTP fixtures, runs the suites, and tears down only that generated Compose project and its temporary credentials. Locally, Compose uses `--pull never`; missing cached images fail before service startup.

The HTTP gate fails when it discovers zero suites, executes zero `node:test` cases, or runs only skipped cases. These checks cover real HTTP behavior against PostgreSQL, not just Lua handlers with a fake database. Funding coverage exercises record retrieval, repeated filters, and pagination. Badge-definition coverage exercises retrieval with an icon and allowed-issuer list, publisher-sidecar hydration, author and badge-type filters, createdAt/URI pagination ties, and named error responses. Badge-query coverage exercises baseline-aware definition feeds and discriminating filters, exact-version award/response lookups, recipient status, raw response history, bidirectional tied pagination, nullable sidecars, and named runtime errors. Vocabulary-tag coverage exercises exact retrieval, author filters, hydrated and nullable sidecars, tied pagination, and named errors. Acknowledgement coverage exercises exact retrieval, hydrated and absent publisher sidecars, repeated author/subject filters, tied pagination in both directions, and named errors. Feature coverage exercises exact retrieval and author hydration, list filters and sidecars, tied createdAt/URI pagination, and named errors. Contribution coverage exercises exact-record retrieval, repeated publisher filters, tied ascending/descending cursor pagination, nullable publisher sidecars, and named errors. Fixtures use CBOR-derived record CIDs and are seeded only into the task-owned disposable database.

Expand Down Expand Up @@ -140,6 +140,16 @@ HAPPYVIEW_BASE_URL='https://your-happyview.example' HAPPYVIEW_ADMIN_TOKEN='<scop

Review that release's notes and target only an explicitly approved HappyView instance.

## Rights queries

- `org.hypercerts.claim.getRights` accepts the exact rights-record AT-URI with a DID authority. An unindexed record returns `RecordNotFound`.
- `org.hypercerts.claim.listRights` accepts up to 100 repeated, unbracketed `authors` keys; values use OR. Pages default to 25 and cap at 100. Ordering uses `(createdAt, uri)`; missing or malformed record timestamps fall back to `indexed_at`, then row creation time. Cursors are opaque and bound to sort direction; a terminal page omits `cursor`.
- Both queries preserve the full indexed record and hydrate the publisher's Certified profile and raw organization sidecar. Missing author records are `null`; SQL `NULL` `indexed_at` is returned as JSON `null` without inventing a timestamp. Query or hydration failures return errors. Attachments and activities referencing rights are not expanded.
- The unpublished `rightsView` response definition is local to `org.hypercerts.claim.getRights`; `listRights` references that definition. Its `indexedAt` property is required but nullable to match indexed rows. Older proposal prose that describes it as non-nullable is stale.
- Rights listing uses PostgreSQL 16+ `pg_input_is_valid` timestamp validation; the canonical HappyView deployment and test configurations default to PostgreSQL 17.

The shared module registers the pinned rights-record Lexicon with backfill enabled, so an approved install can index existing rights records.

The installer validates all local assets and dependencies before making admin requests, then checks installed versions before writing. By default, any conflicting declared asset stops the install before asset writes. Pass `--override` to replace only conflicting assets declared by this bundle; it does not affect undeclared assets or bypass source/dependency validation, admin authentication, or the profile resolver-setting requirements. Use `--debug` to include incoming and installed values in conflict errors, or `--help` to list the options.

`pnpm install:api` contacts a HappyView instance and uploads declared assets; do not run it without an explicitly approved target and token. Writes are not rolled back if a later asset fails.
Expand Down
62 changes: 62 additions & 0 deletions api/lexicons/org.hypercerts.claim.getRights.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"lexicon": 1,
"id": "org.hypercerts.claim.getRights",
"defs": {
"main": {
"type": "query",
"description": "Looks up one indexed rights record by exact DID-authority AT-URI. Authentication is not required.",
"parameters": {
"type": "params",
"required": ["uri"],
"properties": {
"uri": {
"type": "string",
"format": "at-uri",
"description": "Full AT-URI of a rights record, using a DID authority."
}
}
},
"output": {
"encoding": "application/json",
"schema": {
"type": "ref",
"ref": "#output"
}
},
"errors": [
{
"name": "InvalidRequest",
"description": "The URI is invalid or does not identify a rights record."
},
{
"name": "RecordNotFound",
"description": "No indexed rights record exists at this AT-URI."
}
]
},
"rightsView": {
"type": "object",
"description": "Rights record with its publisher actor; the full record is preserved and attachments are not expanded.",
"required": ["uri", "cid", "indexedAt", "did", "author", "record"],
"nullable": ["indexedAt"],
"properties": {
"uri": { "type": "string", "format": "at-uri" },
"cid": { "type": "string", "format": "cid" },
"indexedAt": { "type": "string", "format": "datetime" },
"did": { "type": "string", "format": "did" },
"author": { "type": "ref", "ref": "org.hypercerts.api.defs#actorView" },
"record": { "type": "ref", "ref": "org.hypercerts.claim.rights" }
}
},
"output": {
"type": "object",
"required": ["rights"],
"properties": {
"rights": {
"type": "ref",
"ref": "#rightsView"
}
}
}
}
}
69 changes: 69 additions & 0 deletions api/lexicons/org.hypercerts.claim.listRights.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"lexicon": 1,
"id": "org.hypercerts.claim.listRights",
"defs": {
"main": {
"type": "query",
"description": "Lists indexed rights records with an optional publisher-DID filter. Authentication is not required.",
"parameters": {
"type": "params",
"properties": {
"authors": {
"type": "array",
"maxLength": 100,
"description": "Publisher DIDs; repeat the unbracketed key for multiple authors. Values use OR.",
"items": {
"type": "string",
"format": "did"
}
},
"sortDirection": {
"type": "string",
"enum": ["asc", "desc"],
"description": "Direction for the (createdAt, uri) order; defaults to desc."
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Maximum records in the page; defaults to 25."
},
"cursor": {
"type": "string",
"description": "Opaque cursor from a previous page; keep the sort direction unchanged."
}
}
},
"output": {
"encoding": "application/json",
"schema": {
"type": "ref",
"ref": "#output"
}
},
"errors": [
{
"name": "InvalidRequest",
"description": "An author, sort direction, page bound, cursor, repeated scalar, or query parameter is invalid."
}
]
},
"output": {
"type": "object",
"required": ["rights"],
"properties": {
"rights": {
"type": "array",
"items": {
"type": "ref",
"ref": "org.hypercerts.claim.getRights#rightsView"
}
},
"cursor": {
"type": "string",
"description": "Opaque cursor for the next page; omitted when there is no next page."
}
}
}
}
}
Loading
Loading