Skip to main content

TapDB
Typed objects, immutable Meridian EUIDs, lineage, audit, and discoverable DAG surfaces for Python services.

CI PyPI Python versions

Operate · Prepare a service · Embed · Discover · Federate · Model · Recover

Why TapDB

TapDB is a reusable persistence substrate for services that need typed, versioned objects with stable identifiers and authoritative relationships. It provides templates, generic instances, immutable EUIDs, lineage, audit history, transactional messaging records, and authenticated embeddable web surfaces.

TapDB is not an untyped graph database, workflow engine, or domain application. The owning service defines business meaning and access policy. Relationships belong in generic_instance_lineage; metadata may support display and search, but never becomes the relationship authority.

Install

TapDB 10.1.0 is published on PyPI and GitHub. Artifact hashes and fresh public installation are verified. Independent acceptance is user-attested; CI and formal GitHub review were explicitly waived through an owner-authorized administrative merge, not reported passed. See the release handoff for exact provenance, qualification limitations and service adoption ordering.

The 10.1.0 release requires Python 3.12 or newer. Its database scope targets exact community PostgreSQL 16.13 plus isolated Aurora PostgreSQL 16.13 acceptance. PostgreSQL 17 qualification is deferred to GitHub issue #107 and has not passed; this is not a declaration that PostgreSQL 17 is unsupported.

The receipt-bound runtime-principal bind revokes database TEMP from PUBLIC and the configured runtime principal. When the reviewed plan shows that revocation would remove the operator's pre-existing effective TEMP, it records an explicit operator preservation grant. This database-wide change also affects other roles that relied on PUBLIC TEMP; applications that need temporary objects require an explicit design change. Service adoption must close and recreate existing runtime sessions because TapDB does not terminate them or claim that existing temporary objects were removed. The qualified managed-allocator resolution remains required defense in depth.

python -m pip install "daylily-tapdb[cli,gui]"

TapDB pins meridian-euid==0.4.8. Consumers must not replace that pin with an unverified range or synthesize strings that resemble Meridian EUIDs.

Quick start

From a source checkout:

source ./activate
tapdb --help
tapdb --config <path> ...
tapdb --config <path> bootstrap local --no-gui
tapdb --config <path> --json info

Every stateful command takes one explicit config path. There is no environment selector, ambient database discovery, or implicit fallback target. Config initialization records the client, logical database, physical database, schema, Meridian domain, prefix registry, and owner repository in one file.

Runnable examples live in the repository:

The public Meridian registry is maintained by lsmc-bio/meridian-registry. For example, validate domain Q with:

meridian-euid domain-check Q \
  --registry-index /abs/path/to/meridian-registry/registry/generated/domains.json

Domain registration does not grant a prefix claim. The explicit TapDB prefix ownership registry remains authoritative for prefixes.

Object model

TapDB stores four primary kinds of durable facts:

Fact Authority
Object shape and version generic_template
Persisted typed object generic_instance
Object-to-object relationship generic_instance_lineage
Actor-attributed change evidence audit_log

All runtime PostgreSQL access installs schema, config identity, domain, owner, tenant, actor, and global-row policy together inside the transaction. Row-level security is forced on protected tables. Runtime roles with SUPERUSER or BYPASSRLS are rejected. Schema apply and receipt-bound migration also revoke CREATE on the managed TapDB schema from PUBLIC and its runtime role, while leaving runtime DML grants unchanged. Schema operators must use the distinct migration connection role; application startup, reads, and writes must never create schema objects, including through CREATE TABLE IF NOT EXISTS.

Bundled templates

The core pack contains exactly ten substrate templates:

Category / type / subtype Purpose
actor/user/system Optional bundled GUI/auth user actor; not a universal business primitive
set/generic/generic Generic set
governance/validator/definition Validator definition
governance/terminology/set Terminology set
governance/relationship/constraint Lineage constraint
governance/position/scheme Position scheme
evidence/repair/record Explicit repair evidence
reference/external_identifier/tapdb_object Typed external object reference
reference/external_identifier/opaque Scoped non-federated external identifier
message/webhook/event Transactional webhook event

Application-specific templates belong in the consuming repository and are loaded explicitly. Core and consumer packs cannot silently override one another.

The database operator materializes the exact installed core definitions inside each configured owner scope, allowing that owner's constrained runtime to use typed XRF/SYS/MSG objects without owning TapDB's reserved prefixes. A copied path or modified client-authored template cannot unlock reserved-prefix seeding.

Python API

Use the factory inside a caller-owned transaction. Natural identity claims are atomic and distinguish a new object from an idempotent replay:

from daylily_tapdb import (
    IdentityScope,
    InstanceFactory,
    TAPDBConnection,
    TemplateManager,
)

manager = TemplateManager()
factory = InstanceFactory(manager, domain_code=domain_code)

with connection.session_scope(commit=True) as session:
    claim = factory.claim_instance_by_identity(
        session,
        template_code="message/webhook/event/1.0/",
        identity_key=event_identity_key,
        name="Webhook event",
        scope=IdentityScope.GLOBAL,
        properties=event_properties,
        command_evidence={"source": "consumer"},
    )
    persisted_euid = claim.instance.euid

Any replay of the same identity key returns EXISTING and the stored winner; TapDB does not compare consumer payload fingerprints. A race-safe consumer such as Dewey first claims or reads the committed stored winner, then compares its client-owned fingerprint and returns its own divergent-payload 409 without creating a second receipt. The claim API requires an already-active transaction and never commits or rolls back its caller's transaction.

Canonical external references

TapDB 10 has one external-reference model and one writer. A local source points through persisted lineage to a shared, typed XRF object. A federated target names an exact TapDB service and an EUID that service actually persisted; an opaque target names a non-expandable external identifier such as a DOI or PMID.

from datetime import UTC, datetime

from daylily_tapdb.external_references import (
    ExternalLinkSpec,
    ExternalReferenceService,
    TapDBObjectTarget,
)

target = TapDBObjectTarget(
    target_service_id="atlas",
    target_object_euid=remote_object_euid,
    target_object_kind="analysis",
)
spec = ExternalLinkSpec(
    target=target,
    relationship_type="references",
    assertion_authority="catalog-sync",
    asserted_at=datetime.now(UTC),
    assertion_provenance=sync_receipt,
)

with connection.session_scope(commit=True) as session:
    outcome = ExternalReferenceService(session).attach(source, spec)

attach, detach, authority-scoped reconcile, list_for_source, and find_sources all participate in the caller's transaction. Replays reuse the same reference and lineage; reactivation keeps the lineage UID and EUID. Applications still own remote validation, credentials, synchronization, business status, and fleet configuration.

There is no URL-bearing reference shape, metadata-derived edge, generic XRF writer, or legacy GUI writer. Use the external-reference and federation guide for scopes, failure modes, reverse lookup, migration guidance, and complete API examples.

Discoverable DAG v2

Hosts mount the authenticated v2 contract atomically. A failed mount publishes no advertisement and registers no partial routes:

from fastapi import FastAPI

from daylily_tapdb.web import DagV2Limits, mount_tapdb_dag_surfaces

app = FastAPI()
result = mount_tapdb_dag_surfaces(
    app,
    config_path="/abs/path/to/tapdb-config.yaml",
    service_id="catalog-api",
    display_name="Catalog API",
    auth_dependency=require_service_or_user,
    limits=DagV2Limits(
        max_depth=6,
        max_nodes=500,
        max_search_page_size=100,
    ),
)
if not result.mounted:
    raise RuntimeError(f"DAG v2 unavailable: {result.reason}: {result.diagnostic}")

The mount exposes:

  • GET /api/dag/manifest
  • GET /api/dag/v2/object/{euid} for exact ownership lookup
  • GET /api/dag/v2/data for bounded native traversal
  • GET /api/dag/v2/search for bounded opaque-cursor discovery

Every route requires auth. The immutable service_id must exactly match fleet registration. Search results are discovery candidates, not ownership proof; consumers confirm ownership with exact lookup. Graph responses include a revision, snapshot time, presentation metadata, effective limits, and explicit truncation. DAG v2 projects only outbound typed references backed by a persisted external-reference object plus lineage, and it never fetches a remote v2 service on the caller's behalf.

Exact external-reference search is part of the same endpoint. Supply either external_service_id plus external_object_euid, or external_namespace, external_kind, and external_value; an optional external_relationship_type narrows either group. Incomplete or mixed groups fail with 422.

daylily_tapdb.federation.DagV2FederationClient composes authenticated DAG-v2 services for Kahlo-style global search and visualization. The application provides an exact service inventory and its authenticated transport; TapDB validates manifests, namespaces IDs as service_id::euid, follows canonical references under hard limits, and returns per-service receipts and unresolved boundaries. TapDB does not discover endpoints, own credentials, forward auth, retry aliases, or fall back to another protocol.

See the runnable request flow, eligibility reasons, adoption checklist, and anti-patterns in the consumer discoverability guide.

Web and GUI embedding

daylily_tapdb.gui is the only TapDB web implementation. Its standalone and embedded forms share the same auth/account, overview, search, template, object, lineage, repair, audit, inventory, readiness, Meridian, metrics, runtime, backup/recovery, and graph features. The graph explorer retains search, filters, layouts, neighborhood and lineage gestures, detail inspection, JSON export, and Mermaid export; it consumes canonical DAG v2 only.

TapdbHostBridge supplies host identity, navigation, and styling without giving TapDB authority over application policy:

from fastapi import FastAPI

from daylily_tapdb.gui import create_tapdb_gui_app
from daylily_tapdb.web import TapdbHostBridge

app = FastAPI()
tapdb_gui = create_tapdb_gui_app(
    config_path="/abs/path/to/tapdb-config.yaml",
    host_bridge=TapdbHostBridge(
        auth_mode="host_session",
        service_name="catalog-api",
        app_name="Catalog API",
        resolve_user=resolve_host_user,
        login_url="/login",
    ),
)
app.mount("/tapdb", tapdb_gui)

The former admin.main ASGI app, DAG v1 router, outbound proxy, legacy graph payload adapter, URL-bearing external graph merge, and embedded external-link writer do not exist in 10.0. There is no compatibility alias or fallback.

Development and release checks

python -m pytest tests/ -q
ruff check daylily_tapdb admin tests
ruff format --check daylily_tapdb admin tests
mypy
bandit -c pyproject.toml -r daylily_tapdb admin
python -m build

The checked-in release CI is configured to run the same complete suite independently against exact community PostgreSQL 16.13, including local-doc examples and branch coverage, with separate isolated Aurora PostgreSQL 16.13 acceptance. The shared release gates also run Ruff, mypy, Bandit, detect-secrets, wheel build, schema/migration asset verification, and installed-wheel smoke checks. CI does not hide integration tests with deselects. These configured gates are not a success claim until one frozen, reviewed candidate passes them. PostgreSQL 17 results remain evidence for the deferred qualification, not 10.1.0 acceptance. The mypy file list in pyproject.toml covers the new 10.1 implementation modules; older dynamically mapped ORM and Typer modules are not yet globally strict-clean.

For 10.1.0 only, the user approved the measured changed-module coverage exceptions daylily_tapdb/backup/recovery.py at 86.72% and daylily_tapdb/backup/service.py at 89.57%. Their numeric reports remain required. Aggregate branch coverage and every other changed production module must remain at or above 90%; the exceptions do not waive functional tests, PostgreSQL/Aurora acceptance, or review.

The frozen-candidate PostgreSQL/Aurora acceptance must also verify the reviewed database ACL, PUBLIC and runtime TEMP revocations, any explicit operator TEMP preservation grant, and effective TEMP=false from a newly created runtime session. The isolated author checks passed; independent acceptance is user-attested. The10.1.0 release's CI/formal-review gate was separately waived by explicit owner authorization; this does not change normal future CI gates.

Documentation

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

daylily_tapdb-10.1.5.tar.gz (1.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

daylily_tapdb-10.1.5-py3-none-any.whl (677.0 kB view details)

Uploaded Python 3

File details

Details for the file daylily_tapdb-10.1.5.tar.gz.

File metadata

  • Download URL: daylily_tapdb-10.1.5.tar.gz
  • Upload date:
  • Size: 1.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for daylily_tapdb-10.1.5.tar.gz
Algorithm Hash digest
SHA256 05bcd91c3dc2a6f0fec3695ca2f81b34cc34c6db5d11e16a5000ae1d657566c8
MD5 12b1f7ee780018a5a0f086dc39a971e6
BLAKE2b-256 634ba683ae984e2043b358a8d60c3844109c3fca6022e983d5b40cb714e1c030

See more details on using hashes here.

File details

Details for the file daylily_tapdb-10.1.5-py3-none-any.whl.

File metadata

  • Download URL: daylily_tapdb-10.1.5-py3-none-any.whl
  • Upload date:
  • Size: 677.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for daylily_tapdb-10.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 728e9e83ed6d5f596af9f1c5b3d5a83134d2dd9ef30da83c752e3c5170fc092d
MD5 ab7a3ae993b496b91ac49abf8da4be97
BLAKE2b-256 dee4145909f82d349fbb6f2c5898bd8536b3d455c1afe7e6241eacbccef58ead

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

10.1.5 This release

2 files

10.1.4

2 files

10.1.3

2 files

10.1.2

2 files

10.1.1

2 files

10.1.0

2 files

10.0.0

2 files

9.2.2

2 files

9.2.1

2 files

9.2.0

2 files

9.0.10

2 files

9.0.9

2 files

9.0.0

2 files

8.0.6

2 files

8.0.5

2 files

8.0.2

2 files

8.0.1

2 files

8.0.0

2 files

7.0.12

2 files

7.0.11

2 files

7.0.9

2 files

7.0.8

2 files

7.0.7

2 files

7.0.5

2 files

7.0.4

2 files

7.0.3

2 files

7.0.2

2 files

7.0.1

2 files

7.0.0

2 files

6.0.13

2 files

6.0.12

2 files

6.0.11

2 files

6.0.9

2 files

6.0.8

2 files

6.0.7

2 files

6.0.5

2 files

6.0.4

2 files

6.0.3

2 files

6.0.2

2 files

6.0.1

2 files

6.0.0

2 files

5.1.0

2 files

5.0.4

2 files

5.0.3

2 files

5.0.2

2 files

5.0.0

2 files

4.1.4

2 files

4.1.3

2 files

4.1.2

2 files

4.1.1

2 files

4.1.0

2 files

4.0.11

2 files

4.0.10

2 files

4.0.9

2 files

4.0.7

2 files

4.0.6

2 files

4.0.5

2 files

4.0.4

2 files

4.0.3

2 files

4.0.2

2 files

4.0.0

2 files

3.2.5

2 files

3.2.4

2 files

3.2.3

2 files

3.2.2

2 files

3.2.1

2 files

3.2.0

2 files

3.1.0

2 files

3.0.12

2 files

3.0.11

2 files

3.0.10

2 files

3.0.9

2 files

3.0.8

2 files

3.0.7

2 files

3.0.6

2 files

3.0.5

2 files

3.0.4

2 files

3.0.3

2 files

3.0.2

2 files

3.0.1

2 files

0.2.7

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.1.39

2 files

0.1.38

2 files

0.1.37

2 files

0.1.35

2 files

0.1.33

2 files

0.1.32

2 files

0.1.30

2 files

0.1.29

2 files

0.1.28

2 files

0.1.27

2 files

0.1.26

2 files

0.1.25

2 files

0.1.24

2 files

0.1.23

2 files

0.1.22

2 files

0.1.21

2 files

0.1.19

2 files

0.1.17

2 files

0.1.16

2 files

0.1.15

2 files

0.1.13

2 files

0.1.12

2 files

0.1.11

2 files

0.1.9

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page