pdt 0.3.5

Asset store API with relation graphs, tagging, full-text search, multi-instance SQLite tenancy, OIDC auth and Cedar authorization
docs.rs failed to build pdt-0.3.5
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

PDT — Platform Data Toolkit

A document/asset store API with relationship graphs, free-form tagging, full-text search, OIDC authentication, and Cedar-based authorization. Runs as a single global instance or as a tree of isolated per-tenant instances, each backed by its own SQLite database.

Features

  • Assets, relations, collections — CRUD with soft deletes, a traversable relation graph, and named collections
  • Free-form tags{category, value} pairs with light validation; no fixed taxonomy
  • Full-text search — SQLite FTS5 with user input safely reduced to quoted phrases
  • Multi-instance tenancyX-Instance-Id routing to per-instance SQLite files, nested provisioning (workspace → agent/company leaves), instance tree listing
  • Two storage backends — MongoDB/DocumentDB (default) or SQLite for the root database
  • OIDC auth + Cedar authorization — JWT validation via a policy enforcement point (pep), Cedar policies enforced per request, audit log with user attribution
  • OpenAPI — machine-readable spec at /api/docs/openapi.json

Quick start

Zero external dependencies with the SQLite root backend:

cargo run --features sqlite-backend --bin pdt
# …or let it read a .env file (dotenvy is loaded automatically):
cp env.example .env

Environment for the above:

PDT_DB_BACKEND=sqlite
SQLITE_PATH=./pdt.db
PDT_INSTANCES_DIR=./instances
AUTH_ENABLED=false
AUTH_DEV_MODE=true

To run against MongoDB/DocumentDB instead (the default build):

DOCUMENTDB_URL=mongodb://localhost:27017
DOCUMENTDB_USERNAME=admin
DOCUMENTDB_PASSWORD=change-me
DOCUMENTDB_DATABASE=pdt

See env.example for the full set of variables.

Multi-instance tenancy

Every request may carry X-Instance-Id. With the header, all entity operations are routed to that instance's own SQLite database under PDT_INSTANCES_DIR; without it, they hit the root database (MongoDB/DocumentDB by default, SQLite with the sqlite-backend feature).

POST /api/instances/{id}/provision?parent={parent_id}   # create an instance DB (optionally nested)
GET  /api/instances                                     # list instances found on disk
GET  /api/instances/tree                                # list as a workspace tree
DELETE /api/instances/{id}                              # delete an instance

Nested provisioning creates {instances_dir}/{parent}/{id}/pdt.db, which gives you workspace → agent/company hierarchies where each leaf is fully isolated: cross-instance reads simply don't resolve. Assets are born with an auth_context (visibility / owner groups / confidentiality) that Cedar policies evaluate.

Authentication and authorization

Write endpoints (and sensitive reads) require Authorization: Bearer <jwt>. Tokens are validated against the configured OIDC issuer (JWKS signature, expiry, audience):

AUTH_ENABLED=true
AUTH_ISSUER_URL=https://idp.example.com
AUTH_AUDIENCE=pdt-api
AUTH_USERINFO_URL=https://idp.example.com/userinfo   # optional claim enrichment

Authorization is delegated to Cedar. Policies live in policies/ (rbac.cedar + schema.cedarschema), are compiled into the binary, and the effective policy set is exposed at GET /api/cedar/policies.

⚠️ AUTH_DEV_MODE=true injects admin claims into any request that carries no bearer token — including when AUTH_ENABLED=true. Never enable it outside local development.

API surface

# Assets
POST   /api/assets                          GET    /api/assets
GET    /api/assets/{id}                     PUT    /api/assets/{id}
DELETE /api/assets/{id}                     # soft delete
POST   /api/assets/{id}/tags                DELETE /api/assets/{id}/tags/{tag_id}
PUT    /api/assets/{id}/auth-context        # update auth context
GET    /api/assets/{id}/relations           GET    /api/assets/{id}/graph
GET    /api/assets/{id}/history

# Relations
POST   /api/relations                       GET/DELETE /api/relations/{id}

# Collections
POST   /api/collections                     GET    /api/collections
GET/PUT/DELETE /api/collections/{id}
POST   /api/collections/{id}/assets         DELETE /api/collections/{id}/assets/{asset_id}

# Search & audit
GET    /api/search?q=…                      GET    /api/audit

# Instances
POST   /api/instances/{id}/provision        DELETE /api/instances/{id}
GET    /api/instances                       GET    /api/instances/tree

# Misc
GET    /health                              GET    /api/cedar/policies

Search

GET /api/search?q=fame workspace — queries are tokenized and each token is phrase-quoted before hitting FTS5, so user input can never be interpreted as FTS query syntax (column filters, boolean operators, etc.). Non-alphanumeric characters are preserved inside quoted phrases, making e.g. Persian text searchable.

Tags

Tags are free-form {category, value} pairs — categories like asset_type are conventions, not enforced values. Validation: category/value are alphanumeric plus hyphens, underscores, and forward slashes, capped at 64 characters.

Relation types

contains, references, related_to, depends_on, supersedes, complements, has_instance, has_agent

Development

cargo test                            # default (mongodb-backend) suite
cargo test --features sqlite-backend  # sqlite root-backend suite

Two binaries are produced by the workspace; --bin pdt selects the server. The sqlite-backend feature gates only the root database repository — instance routing always uses SQLite, so sqlx is compiled in unconditionally.

License

Dual-licensed under MIT or Apache-2.0, at your option.