On this page

API

Changelog and versioning

How the ReuseForge API is versioned, what counts as a breaking change, how deprecations are announced and sunset, and the changelog of every contract release.

Versioning policy

  • The major version is in the URL. Everything documented here lives under /api/v1. A breaking change needs /api/v2, which would run alongside /api/v1.
  • Inside v1, changes are additive only. New endpoints, new optional request fields, new response fields, new enum values, new error codes, new event types, new rate limit tiers. Removing or renaming anything, making validation of an existing field stricter, or changing what something means is not allowed in v1.
  • The contract has a semantic version, 1.MINOR.PATCH, in info.version of the OpenAPI document. Every response carries it in the ReuseForge-Version header and GET /api/v1/ reports it as api_version. Additive releases raise the minor number; clarifications and fixes to the description raise the patch number. Every change is listed in the changelog below.
  • Write tolerant clients. Ignore response fields you do not know. Treat enum values you do not know as "other". Keep a default branch for new error codes (branch on the status class). Accept unknown webhook event types and ignore them. The SDKs preserve unknown fields and do this for you.
  • Webhook payloads carry api_version ("1"), fixed when the endpoint is created. Additive changes show up for every endpoint; a breaking payload change would arrive only in a new api_version that you opt into by creating a new endpoint.

Deprecation and sunset

  1. The operation, field or enum value is marked deprecated: true in the OpenAPI document, announced here, and listed in deprecations of GET /api/v1/.
  2. From then on every response from a deprecated operation carries Deprecation: @<unix time> (RFC 9745), Sunset: <HTTP date> (RFC 8594) and Link: <url>; rel="deprecation".
  3. The minimum notice between deprecation and sunset is 6 months, and 12 months for anything that touches money.
  4. After the sunset date the operation answers 410 gone.

Nothing is deprecated today: deprecations in GET /api/v1/ is an empty list. Watch that field, or the Deprecation header in your logs, rather than this page.

How to follow changes

  • Read the changelog below, or /docs/api/openapi.json (the contract, with info.version).
  • Compare ReuseForge-Version in your own responses with the version you tested against.
  • The SDKs export the contract version they were generated from (CONTRACT_VERSION in JavaScript); an additive API release needs no SDK upgrade, and client.request() reaches new endpoints before the SDK knows them.
  • The docs on these pages are regenerated from the contract, so they never lag the version in info.version.

Changelog

The changelog is the file api/CHANGELOG.md of the repository, newest first. The entry called "Unreleased" describes work that is in the repository but not part of a numbered contract release.

The contract version is info.version in openapi.yaml and is returned in the ReuseForge-Version response header. Inside /api/v1 changes are additive only (see DESIGN.md section 10). Every change to openapi.yaml, the JSON Schemas in schemas/ or the behaviour described in DESIGN.md gets an entry here, newest first. Deprecations are announced here at least 6 months (12 for money) before the sunset date.

Format: ## <version> - <date>, then Added / Changed / Deprecated / Fixed.

Unreleased (OAuth gate review)

Behaviour of the OAuth authorization server (/api/v1/oauth/*, DESIGN.md section 18, docs/OAUTH.md); openapi.yaml and the contract version are unchanged.

Fixed

  • Tokens issued to OAuth-connected apps carry the stored marker oauth and never imply a legacy scope, so they work on /mcp and /api/v1 only; the platform routes under /api/* (profile, organizations, invitations, notifications) answer 403. Before, the four write scopes added up to legacy write (an app could delete the user's organizations).
  • webhooks:manage is no longer grantable through OAuth (an endpoint belongs to the account and kept delivering after the app was disconnected); it is listed as not available on the consent page and dropped from scopes_supported.
  • Per-IP OAuth limits count an IPv6 /64 as one address. Client ID Metadata Documents on the site's own host or a subdomain are refused, client names imitating "ReuseForge" are invalid_client_metadata, redirect URIs whose host ends in a dot are invalid_redirect_uri, and a consent request belongs to the first account that opens it (the CSRF token is bound to that browser session).

Unreleased (planning review, round 2)

Behaviour only; openapi.yaml and the contract version are unchanged.

Changed

  • plan_goal and discover_external schedule connectors with the cost of their first query again, so one online plan asks several sources (every requirement, papers, the MCP registry, Hugging Face); a connector whose first query finds nothing may spend only calls that no other scheduled connector has been promised. The 3 calls kept for enrichment stay out of reach of the search. A source the budget could not cover is skipped and never makes an answer partial; a retry the budget cannot pay for is reported as the failure that caused it.
  • The planner bounds its work per request (at most 2500 expanded partial plans, 32 sets of shared paid blocks per stage); a catalogue of paid items that each fit many requirements yields a thinned front (search_truncated) instead of exhausting the Worker's CPU. A budget and the "what a higher budget buys" hint come from one search.

Fixed

  • Candidate.payout_rails of a hosted item lists the enabled rails on which its seller has a usable payout address (it used to list every enabled rail of the platform); [] means the item cannot be bought yet.
  • A plan that nothing fits because of constraints.kinds alone says to relax a constraint rather than only the budget.

Unreleased (latest: stable first, prerelease fallback)

Behaviour clarification, no schema change. latest resolves to the highest non-yanked, non-quarantined stable version; when an item has no stable version it resolves to the highest live prerelease (before, such an item had no latest and answered 404). This matches the platform's items.latest_version, so the two never overwrite each other. The plugin marketplace still pins stable releases only.

Unreleased (versions group hardening, round 3)

Behaviour only; openapi.yaml and the contract version are unchanged.

Changed

  • request_verification examines at most 1 MiB of stored file content per run. A larger version answers 202 with a record whose state is error (counts null, summary and one limits check saying nothing was checked), never passed.
  • The refused header variables of a remote MCP server (unsafe_header) now also cover source-hosting, package-registry, payment, database and further agent-provider credentials (GITHUB_*, GH_*, HF_*, GOOGLE_*, STRIPE_*, NPM_*, ...). Entries added through an install override's config_patches get the same descriptor warning (variable names and host) as the manifest mcp section. In the descriptor a header value counts as a placeholder only as a whole (${VAR} or Bearer ${VAR}).

Unreleased (versions group hardening, round 2)

Behaviour only; openapi.yaml and the contract version are unchanged.

Changed

  • executable and preview globs may contain at most 8 wildcards and, together, a bounded amount of matching work against the version's own file paths (a literal prefix or suffix makes a glob cheap); otherwise 422 invalid_glob. Matching never backtracks and draws on a work budget.
  • A remote MCP server's headers may not carry cloud, agent-provider, SSH or ReuseForge credential variables (422, error code unsafe_header); the install descriptor names every header variable and the host it is sent to.
  • The secret scan reads every file to its end whatever number of placeholder-looking tokens come first; a flood of them fails the check.

Unreleased (platform wave 2: quarantine, storage quota, review moderation)

Security fixes; the contract version stays at 1.1.0. Additive: two error codes (version_quarantined, review_removed) and the undeclared 403 on three operations.

Fixed

  • get_version_bundle, get_install_descriptor, get_version_archive and get_verification served quarantined versions to anybody. They now answer 403 version_quarantined unless the caller is the owner, a member with write access or an administrator; get_version omits files, manifest and verification for other callers, get_marketplace skips quarantined versions.
  • publish_version scans the version before answering (the verdict is stored with it) and enforces the owner's storage quota: 413 quota_exceeded (20 MB unverified, 200 MB verified email, 1 GB verified publisher), nothing stored.
  • list_reviews and the item's rating and review counters ignore reviews hidden by a moderator and reviews of suspended accounts; delete_review and create_review answer 403 review_removed for a review a moderator removed.
  • latest never resolves to a quarantined version: a blocked newest release falls back to the last clean one, and an item whose versions are all blocked, yanked or prereleases has no latest (install of latest answers 404 with the reason, a named version 403 version_quarantined). update_version bumps the item's rev so each yank is its own item.updated event.

Added

  • Error codes version_quarantined and review_removed (both 403) in ErrorCode; 403 on get_version_bundle, get_install_descriptor and get_version_archive.

Unreleased (items group review, round 2)

Conformance and hardening fixes; the contract version stays at 1.1.0.

Fixed

  • An item removed through the web app or by a moderator follows the same rule as retract_item: 410 gone only when it had been publicly listed (active, not private) at that moment, else 404. A trigger (migration 0312_v1_items_retracted_trigger.sql) marks anything that was not publicly reachable, and lookupItem judges platform removals by the item's listing history.
  • update_item and retract_item no longer move updated_at into the future. Several edits in one second keep the real write time; they are told apart by rev (ETag) and each still fires its own item.updated, with the event key the webhook bridge builds from the row (item, second, rev). Web-app, moderator and suspension writes now move rev too (same migration), so their item.updated cannot share a key with a v1 event.
  • Responses now declared: 410 on update_item, unstar_item and delete_review (a retracted item answers 410 to callers who cannot see it as a member). A test now checks every status the items operations answer against openapi.json.

Unreleased (pipeline, tokens and idempotency hardening, round 3)

Behaviour only; openapi.yaml and the contract version are unchanged.

Changed

  • Tokens with the admin scope default to 7 days and last at most 30 (expires_in_days above 30 answers 422 validation_failed); the description of TokenCreate.expires_in_days says so.
  • Revoking a token gives its parent the unspent part of the allowance reserved for it, counting what its whole subtree of child tokens really committed (before, allowance reserved by revoked descendants was lost to the root for good).
  • spend_limit_exceeded explains that spent_cents also counts allowance set aside for tokens the token created.
  • Idempotency claims are limited to 300 per account and hour (all tokens and sessions of the account together); beyond that a keyed POST answers 429 rate_limited with Retry-After before anything is stored, and the same key and request can be retried later. Replays do not take a new claim.

Unreleased (webhooks review, round 1)

Security and conformance fixes of the webhook surface; the contract version stays at 1.1.0. Additive: one new field (EventBase.data.truncated) and previously undeclared error statuses.

Added

  • data.truncated (boolean) in EventBase: documents the shrunk body of an event above 256 KiB.
  • 409, 410 and 503 on redeliver_webhook; 503 on create_webhook, rotate_webhook_secret and test_webhook; 409 already_exists on create_webhook and update_webhook. The handlers always answered them; they were undeclared.

Changed

  • Subscribing to an event type, changing the URL of an endpoint and redelivering an event need the read scope of the type (orders:read, items:read, projects:read) in addition to webhooks:manage, else 403 insufficient_scope (DESIGN section 11). Before, webhooks:manage (and so the legacy write scope) was a read of all event data.
  • One endpoint per URL and account (409 already_exists).
  • item.retracted events carry the retraction stub of the contract; project.milestone.approved events carry the Milestone and data.project_id; two changes of one item in the same second are two events; listing an item again is a new item.published.
  • A delivery blocked by the SSRF policy fails at once (ssrf_blocked, no retry); a 410 to a ping no longer disables the endpoint; redelivering a ping counts toward the ping limit; failures on our side (signing key, DNS-over-HTTPS) no longer use up the retry schedule; the notice about a disabled organization endpoint goes to the organization's current owners and admins and names the host only.
  • The reference verifier uses the reason codes of conformance/webhook-vectors.json.
  • The SSRF classifier also refuses fec0::/10, 64:ff9b:1::/48 and the ORCHID ranges.

Unreleased (versions group review, round 1)

Security and conformance fixes; the contract version stays at 1.1.0.

Fixed

  • The read routes of the versions group (list_versions, get_version, get_version_bundle, get_install_descriptor, get_verification) judge visibility and membership with items:read, like the items group: a token without it no longer reads private or draft items, org members' paid content, or (for admins without the admin scope) other accounts' content.
  • A removed item is no longer distributed to accounts that installed it before a moderator removed it; after the owner's own retraction they keep reading it. get_install_descriptor answers 404 (not 410) for removed items that were never public.
  • Install overrides: destinations are an allow-list (see DESIGN section 13), Windows/NTFS/8.3 aliases are refused, config_patches can only add the item's own MCP server entry, commands may not hide characters, MCP urls are https, header placeholders are anchored. New error codes in errors[]: unsafe_patch, unsafe_command, invalid_glob, unsafe_url.
  • File paths: segments ending in . or a space, containing :, naming Windows devices or holding invisible format characters are refused (invalid_path); duplicate detection is case-folded and also covers file/directory conflicts.
  • Globs of executable and preview are matched in linear time and limited to 8 wildcards; manifest.preview is applied to the files.
  • Verification messages no longer quote file content; the secret scan counts only reported hits and also reads files that are not UTF-8 text.
  • Concurrent publishes of the same canonical version can no longer both succeed (409 for the loser).
  • list_versions?limit=100 no longer exceeds D1's 100 bound parameters, and legacy content hashes are cached with one batch.
  • ItemVersion.archive_sha256 is now emitted (null until the plain ZIP exists, always null for paid items).
  • update_version rejects latest (400 invalid_parameter).

Unreleased (distribution review, round 1)

Security and conformance fixes for get_version_archive and get_marketplace; the contract version stays at 1.1.0. The archive builder revision (FORMAT) moves to 2, so every cached digest is recomputed once; pinned digests of existing marketplace entries change once (migration 0305_v1_archive_digests_kind.sql).

Fixed

  • The claude-plugin layout is built from the stored, validated manifest only. A file named reuseforge.json is plain content: it no longer produces .mcp.json, plugin.json fields, executable bits or the prompt main file. A version published without a manifest has no mcp section, so an mcp_server version cannot be packaged; literal env values and invisible characters in a stored mcp section are refused again at build time.
  • The layout no longer follows the mutable item kind unnoticed: the layout is refused (400, or left out of the marketplace) once the item's kind differs from the kind in the version's stored manifest, and digests are cached per (version, layout, kind), so a kind change can neither answer 304 for changed bytes nor leave the marketplace pinning a stale sha256.
  • executable globs are matched by a linear-time matcher with a step budget (a hostile pattern gives a 400, not minutes of CPU), and with the same grammar and wildcard cap as the install descriptor (leading ./ dropped, NFC for pattern and path, at most 8 wildcard runs).
  • plugin.json drops description, license and keywords that contain bidi, zero-width or other invisible characters.
  • The ZIP writer refuses entry names that collide on case-insensitive or normalising filesystems and a file that is also a directory.
  • get_marketplace: one query for all versions (no query per prerelease-latest item), an explicit D1 query budget for cold builds, a build that never finished is not retried by every request (15 minutes, 3 attempts) and an unexpected build error leaves only that entry out. The listing cap is 100 plugins and is announced by X-ReuseForge-Marketplace-Truncated. Entries carry keywords (and tags). A 304 keeps X-ReuseForge-Marketplace-Pending and X-Content-SHA256.
  • get_version_archive: a remembered "cannot be packaged" verdict is answered without loading the files or writing again; an unarchivable stored path is no longer blamed on layout; 1.0.0 resolves a published 1.0.0+build like get_version.
  • Documented: the claude-plugin file name suffix, X-RF-Yanked, 410 Gone on get_version_archive.

Unreleased (items group review, round 1)

Security and conformance fixes; the contract version stays at 1.1.0.

Fixed

  • Retracting a draft, archived or private item no longer turns its 404 into a 410: 410 gone is answered only for items that were publicly listed (active, not private) when they were retracted (migration 0311_v1_items_retracted.sql).
  • create_review on a paid item needs a RELEASED order (as documented); a funded or delivered order in escrow is not enough.
  • unstar_item on an item the caller can no longer see answers stars_count: 0 instead of the live count.
  • search_items binds at most 16 query tokens (one LIKE parameter each) and no longer fails with 500 on long dotted or path-like queries; sort=relevance pages seek from the last row's current rank, so rows are not repeated or skipped when the index changes between pages.
  • Un-starring takes the star out of the daily counter of the day it was counted on, so star/unstar cycles across UTC midnights cannot inflate trending.
  • update_item: the write is conditional on the status, visibility and updated_at that were read as well as rev, so a web-app edit or a moderator takedown in between is a 412, never silently overwritten or undone; updated_at is strictly increasing, so two edits in one second each fire their own item.updated.
  • ETag of an item: the first 8 hex characters now identify the editable state and the last 8 the whole representation. If-Match on update_item holds while the editable state is unchanged, so a star, download or review by somebody else no longer causes a 412. The tag stays 16 hex characters and opaque.
  • Webhooks: item.retracted carries {id, object, full_name, status, retracted_at} as ItemRetractedEvent requires; item.published and item.updated carry the Item without readme and without the actor's viewer block.
  • Titles, summaries, source refs and review titles reject invisible format characters (Unicode tag characters, soft hyphen, invisible operators, fillers, bidi controls). READMEs and review bodies reject text-hiding and text-reordering characters (tag characters, zero width space, word joiner, bidi embeddings, overrides and isolates); LRM, RLM and joiners remain allowed.
  • get_item_stats returns totals.revenue_cents to owners and organization admins when the payments ledger reports a figure, and omits it otherwise.

Changed

  • ItemCreate.slug pattern is now ^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$ (no trailing ., _ or -), which is what the server always enforced; the schema now says so instead of answering invalid_slug to schema-valid input.
  • ItemUpdate no longer promises that null clears fields (the server never accepted null): send an empty string, or an empty array for tags and capabilities.
  • Responses now declared: 409 on update_item (retracted item), 410 on list_reviews, get_item_stats, star_item and create_review, 403 on delete_review.

Unreleased

Hosted MCP server hardening (security review). The REST contract is unchanged except for two MCP annotations.

Changed

  • x-mcp.readOnly is now false for get_install_descriptor (it records an install) and plan_goal (it stores a plan and spends quota): clients that auto-approve read-only tools no longer run them unprompted. scripts/validate_openapi.py lets get_install_descriptor be a GET tool that is not read-only.
  • MCP money tools (create_order, pay_order, accept_order, refund_order_item, back_project, transfer_units) require an idempotency_key argument; the server no longer derives one for them from the JSON-RPC id. Other POST tools keep the derived key. A replayed result is announced in content[0] (REPLAYED: ...).
  • MCP create_order no longer has a root oneOf in its inputSchema (the choice is in the description).
  • MCP batches (protocol 2025-03-26) may hold at most one tools/call, resources/read or completion/complete.
  • MCP resources/read returns the complete document and maps 4xx problems to -32602 with retry_after; install descriptors keep paths, commands and config text byte-exact (see DESIGN section 18).

Fixed

  • A tool argument that is . or .. could address another operation (get_item {item: "../tokens"} ran list_tokens).
  • Look-alike spellings of the </untrusted-data> delimiter and of role tags survived the sanitiser.
  • Undeclared object keys, long identifier-shaped values and an exhausted text budget are no longer a way around wrapping.

OAuth 2.1 for the hosted MCP server. No change to openapi.yaml: the OAuth endpoints are not REST operations, the contract version stays at 1.1.0. Additive only.

Added

  • Authorization server under /api/v1/oauth/ (register, authorize, continue, token, revoke): authorization code with PKCE S256, dynamic client registration, OAuth Client ID Metadata Documents, refresh token rotation with reuse detection, RFC 9207 iss, RFC 8707 resource. Documents: /.well-known/oauth-authorization-server, /.well-known/oauth-protected-resource (also /mcp, /mcp/auth, /api/v1). Access tokens are ordinary rf_ API tokens named OAuth: <client>; see docs/OAUTH.md.
  • /mcp/auth: the MCP endpoint, but anonymous callers get 401 with the OAuth challenge. Operator variable MCP_REQUIRE_AUTH does the same for /mcp.

Changed

  • Every 401 from /mcp now has WWW-Authenticate: Bearer realm="reuseforge", resource_metadata="...", error="invalid_token", ... (it previously had the realm and error only).
  • Server card and /.well-known/mcp: authentication.type is oauth2.1+bearer and authentication.oauth describes the OAuth endpoints (it was null).
  • Migration 0304_oauth.sql (tables oauth_clients, oauth_requests, oauth_codes, oauth_grants, oauth_refresh_tokens).

1.1.0 - 2026-11-03

Distribution formats for tools that understand archives or Claude Code marketplaces but not this API. Additive only.

Added

  • get_version_archive: GET /items/{owner}/{slug}/versions/{version}/archive.zip, a deterministic store-only ZIP (sorted entries, fixed 1980-01-01 timestamps, modes 0644/0755, UTF-8 names) with ETag, X-Content-SHA256 and Content-Disposition; same access and 402 rules as get_version_bundle. Query layout=plain|claude-plugin; the plugin layout wraps skill, prompt and mcp_server items for Claude Code. CLI versions download --format zip; not an MCP tool.
  • get_marketplace: GET /marketplaces/{owner}.json, a hosted Claude Code marketplace of the owner's public, free, active items; every entry is an archive source pinned by SHA-256. Add it with /plugin marketplace add https://reuseforge.com/api/v1/marketplaces/<owner>.json. Not an MCP tool.
  • ItemVersion.archive_sha256 (nullable): digest of the plain ZIP once built; always null for paid items.
  • Schemas ClaudeMarketplace and ClaudePluginEntry, parameter ArchiveLayout, headers XContentSha256, ContentDisposition, ContentLength, tag distribution.
  • Publish manifest key executable (globs of files that are mode 0755 in archives).
  • Reference command line cli/ (reuseforge / rf, DESIGN section 17) covering every x-cli command of this contract, including versions download --format zip [--layout], versions publish and marketplaces get <owner>; no wire change.

Changed

  • ReuseForge-Version and info.version are now 1.1.0 (72 operations).
  • Verification.runner is now the enum static-v1 | platform | community | seller (was platform | community | seller). static-v1 is the hosted in-Worker static runner: request_verification returns 202 with an already-completed record, tests_total / tests_passed count static checks, tests_pass_rate is always null and the runner never changes Item.signals. It does not execute test.command. Clients that treated every tests_total as a test count should check runner first. Existing values are unchanged, so this is additive.
  • New optional member Verification.checks ([{id, status: pass|warn|fail|skip, message, path?}]) with the per-check result of a static run.
  • Behaviour recorded in DESIGN sections 12, 13 and 20: the 402 order_hint.reason values (item_not_purchased, order_not_funded, order_refunded), at most 20 verification runs per version (409 conflict beyond), at most 1000 versions per item, downloads counted once per account per day (not for the owner or org members), and latest skipping yanked and prerelease versions (an item with only prereleases has no latest: 404).

1.0.0 - 2026-11-03

First published version of the public REST API v1 contract. Status: contract only. Nothing under worker/src/v1 implements it yet; the OpenAPI document, the JSON Schemas and the design record are checked by tests/test_openapi_contract.py (structure, project rules, every example validated against its schema).

Added

  • OpenAPI 3.1 document openapi.yaml (generated copy openapi.json) with 70 operations under /api/v1 in these groups: meta, identity, tokens, items, reviews, versions and install descriptors, verifications, planning (plan, brief, external discovery, MCP config, connectors), orders and payouts, projects (crowdfunding, milestones, units), webhooks, and the hosted ledger feed.
  • Conventions: cursor pages {data, next_cursor, has_more, total?}; RFC 9457 application/problem+json errors with 41 stable codes; integer cents (_cents) and basis points (_bps); Idempotency-Key (required for create_order, pay_order, back_project, transfer_units); ETag / If-Match on items; RateLimit-* headers with five tiers; Deprecation / Sunset policy.
  • Twelve scopes (items:read, items:write, items:publish, orders:read, orders:create, orders:pay, orders:accept, projects:read, projects:write, webhooks:manage, tokens:manage, admin) and token spend limits (spend_limit_cents). Releasing escrow needs orders:accept plus confirm: true.
  • Webhooks: 15 event types plus ping, signed with ReuseForge-Signature: t=<unix>,v1=<hex> (HMAC-SHA256), 5 minute tolerance, 24 hour dual-signature secret rotation, 8 retries over about 2 days, auto-disable, SSRF rules.
  • Install descriptors for five targets (generic, claude-code, cursor, codex, mcp-json) with files, config patches, display-only commands and a lock entry.
  • schemas/reuseforge.schema.json (publish manifest reuseforge.json) and schemas/reuseforge.lock.schema.json (lockfile reuseforge.lock, lockfile_version 1), JSON Schema 2020-12.
  • Vendor extensions on every operation: x-scopes, x-rate-limit, x-idempotent, x-mcp, x-cli; SDKs, the CLI and the hosted MCP server are derived from them.
  • DESIGN.md: decision record, signing scheme with a test vector, SDK, CLI and MCP rules, implementation mapping and the list of requests to other parts of the platform.
  • Planner constraints in PlanRequest.constraints: exclude_paid, allowed_licenses, deny_licenses (* suffix matches a prefix), max_risk, prefer_free, require_verified, kinds, max_options_per_requirement. Risk model v2 also reads the signals vulns_critical_high, vulns_total, scorecard, archived, days_since_update and dependents (see worker/src/planner.js and repoblock/planner.py; both are checked against shared golden files).

Known limitations of this version

  • The Cursor and Codex install layouts follow those tools' public conventions but were not verified against the running tools.
  • The signed hosted ledger bridge (list_ledger_events, post_ledger_events for hosted owners) is specified but not built.
  • Several operations need database migrations that do not exist yet (token spend columns, webhooks, verifications, installs, ledger events, version yank reason); see DESIGN.md section 20.

Last updated: