Files
the-custodian/workplans/CUST-WP-0023-tpsc.md
tegwick c7a893f068 feat(tpsc): Third-Party Services Catalog (CUST-WP-0023)
Introduces TPSC for tracking external service dependencies with GDPR
compliance maturity (CNIL/IAPP CMMI scale), pricing model, ToS, and
data retention information across all repos.

Primary data:
- canon/tpsc/{openai,anthropic,gemini,openrouter}-api.yaml — service definitions
- tpsc.yaml in each repo (llm-connect seeded with 4 services)

State-hub additions:
- Migration j7e8f9a0b1c2: tpsc_catalog + tpsc_snapshots + tpsc_entries
- api/models/tpsc.py, api/schemas/tpsc.py, api/routers/tpsc.py
- /tpsc/catalog/, /tpsc/ingest/, /tpsc/snapshots/, /tpsc/report/gdpr endpoints
- 4 MCP tools: register_service, list_services, ingest_tpsc_tool, get_gdpr_report
- scripts/ingest_tpsc.py + make ingest-tpsc[/-all] targets
- Dashboard: tpsc.md page + docs/tpsc.md

GDPR maturity scale: unknown | non_compliant | initial | developing | defined | managed | certified
Warnings triggered at: unknown, non_compliant, initial

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 00:15:26 +01:00

5.2 KiB

id, type, title, domain, status, owner, topic_slug, created, updated, state_hub_workstream_id
id type title domain status owner topic_slug created updated state_hub_workstream_id
CUST-WP-0023 feature Third-Party Services Catalog (TPSC) custodian done custodian-agent custodian 2026-03-19 2026-03-20 23208a99-0ef6-4154-9454-a2f2065b6b19

TPSC — Third-Party Services Catalog

Track external service dependencies (APIs, SaaS, CLIs) across all repos. Primary data lives in repos (tpsc.yaml) and a canon catalog (canon/tpsc/<slug>.yaml). State-hub collects and reports.

GDPR maturity scale (CNIL/IAPP CMMI-aligned): unknown | non_compliant | initial | developing | defined | managed | certified

Pricing model: free | paid | freemium | usage_based | unknown

Task: DB migration — tpsc_catalog, tpsc_snapshots, tpsc_entries

id: CUST-WP-0023-T01
status: done
priority: high
state_hub_task_id: "038a0284-bb76-4ce7-8861-1686667acbb5"

Create Alembic migration j7e8f9a0b1c2_tpsc.py.

Tables:

  • tpsc_catalog: id, slug (unique), name, provider, category, website_url, pricing_model, gdpr_maturity, gdpr_notes, dpa_available, tos_url, privacy_policy_url, data_processing_regions (JSON), data_retention_notes, status (active/deprecated), created_at, updated_at
  • tpsc_snapshots: id, repo_id (FK managed_repos nullable), snapshot_at, source_file, entry_count
  • tpsc_entries: id, snapshot_id (FK), catalog_id (FK tpsc_catalog nullable), service_slug, purpose, auth_type, endpoint_override, notes

Task: SQLAlchemy models

id: CUST-WP-0023-T02
status: done
priority: high
state_hub_task_id: "990d4e58-35b0-45f0-8de6-8955049aa7d5"

Create api/models/tpsc.py with TPSCCatalog, TPSCSnapshot, TPSCEntry models. Register in api/models/__init__.py.


Task: Pydantic schemas

id: CUST-WP-0023-T03
status: done
priority: high
state_hub_task_id: "5feeb161-b654-4e4a-8a6a-bb685c239ce5"

Create api/schemas/tpsc.py with Read/Create schemas for all three models. Include GDPRMaturity and PricingModel string enums. TPSCCatalog schema: include gdpr_warning: bool computed field (True when gdpr_maturity in [unknown, non_compliant, initial]).


Task: FastAPI router /tpsc/

id: CUST-WP-0023-T04
status: done
priority: high
state_hub_task_id: "593471b4-cd3a-4251-8c5c-ee42b6a9e089"

Create api/routers/tpsc.py:

  • GET /tpsc/catalog/ — list services (filter: gdpr_maturity, category, pricing_model)
  • GET /tpsc/catalog/{slug} — single service
  • POST /tpsc/catalog/ — register/upsert service
  • POST /tpsc/ingest/ — accept snapshot + entries for a repo
  • GET /tpsc/snapshots/ — list snapshots (filter: repo_slug)
  • GET /tpsc/report/gdpr — aggregated GDPR warnings across all repos

Register in api/main.py.


Task: MCP tools

id: CUST-WP-0023-T05
status: done
priority: high
state_hub_task_id: "7370d020-06cf-4ebe-9f78-619e41c4b85c"

Add to mcp_server/server.py:

  • register_service(slug, name, provider, pricing_model, gdpr_maturity, ...)
  • list_services(gdpr_maturity?, category?, pricing_model?)
  • ingest_tpsc_tool(repo_slug) — runs ingest_tpsc.py for the repo
  • get_gdpr_report() — returns warning summary across all repos

Task: Ingest script

id: CUST-WP-0023-T06
status: done
priority: high
state_hub_task_id: "5ec305d3-fdfb-4f81-b3ab-1ea57a4ec0c5"

Create scripts/ingest_tpsc.py:

  • Reads tpsc.yaml from repo root (auto-detected via registered local_path)
  • Resolves catalog_id by slug for each entry
  • POSTs snapshot + entries to /tpsc/ingest/
  • --dry-run flag
  • --repo SLUG or --all flags

Add Makefile targets:

make ingest-tpsc REPO=<slug>
make ingest-tpsc-all

Task: Canon service catalog seed files

id: CUST-WP-0023-T07
status: done
priority: medium
state_hub_task_id: "21c13b4d-585a-4a60-a283-29baa2dd6d7d"

Create canon/tpsc/ with YAML files for:

  • openai-api.yaml
  • anthropic-api.yaml
  • gemini-api.yaml
  • openrouter-api.yaml

Each file: slug, name, provider, category, pricing_model, gdpr_maturity, gdpr_notes, dpa_available, tos_url, privacy_policy_url, data_processing_regions, data_retention_notes.


Task: tpsc.yaml for llm-connect

id: CUST-WP-0023-T08
status: done
priority: medium
state_hub_task_id: "d658f81b-7408-456d-b4bd-440b44a67e43"

Create /home/worsch/llm-connect/tpsc.yaml declaring: openai-api, anthropic-api (via claude_code CLI), gemini-api, openrouter-api.


Task: Dashboard page

id: CUST-WP-0023-T09
status: done
priority: medium
state_hub_task_id: "a5367fc4-ef12-4f52-b642-d33b91b7cc2c"

Create dashboard/src/tpsc.md:

  • Service catalog table with GDPR maturity color coding (red: non_compliant/unknown, amber: initial/developing, green: defined+)
  • Warning cards for repos using non-green services
  • Per-repo breakdown table
  • Pricing model summary

Add to observablehq.config.js nav.


Task: Documentation page

id: CUST-WP-0023-T10
status: done
priority: low
state_hub_task_id: "6cf1aaec-5c24-4cb5-a1aa-415caeaaca10"

Create dashboard/src/docs/tpsc.md explaining:

  • TPSC concept and rationale
  • tpsc.yaml format with full example
  • GDPR maturity scale definitions (linked to CNIL/IAPP)
  • How to add a new service to the canon catalog

Add to docs nav in observablehq.config.js.