Skip to main content

FastPDLC

Product-as-code as a validated graph — for any project.

Your product intent — the glossary, the constraints, the business rules, the features, the decisions — usually lives as hopeful markdown that quietly rots. FastPDLC turns it into code: you declare your typed artifacts in one config file, and it loads them, enforces the schema and the cross-references, compiles a JSON bundle your app or docs can render, and fails CI when the committed bundle drifts.

It started as the product-as-code engine inside a payments platform and was extracted so any team can use it.

pip install fastpdlc

Quickstart

  1. Describe your artifact types in product.config.yaml:

    product_dir: product
    output: build/product.generated.json
    types:
      - name: terms                 # a glossary
        dir: terms
        id_prefix: "TERM-"          # ids must be TERM-<slug> and match the filename
        required: [id, term, definition]
        fields: [term, definition, see_also]
        references:
          - field: see_also         # every see_also must resolve to another term
            to: terms
      - name: rules                 # the durable invariants
        dir: rules
        id_prefix: "BR-"
        required: [id, title, statement]
        fields: [title, statement]
    
  2. Author artifacts as markdown-with-frontmatter under product/:

    ---
    id: TERM-payment
    term: Payment
    definition: An instruction to move money between two parties.
    see_also: [TERM-ledger]
    ---
    The canonical unit of work in the system.
    
  3. Build the bundle and gate it in CI:

    fastpdlc build       # -> build/product.generated.json  (commit it)
    fastpdlc validate    # schema + graph + staleness; non-zero exit on errors
    

What validate enforces

Every finding carries a stable PAC-NNN code (an API — CI and dashboards match on the code, never the prose):

code meaning
PAC-001 an artifact is missing a required field
PAC-010 an id doesn't start with its type's id_prefix
PAC-011 an id doesn't match its filename
PAC-012 a duplicate id within a type
PAC-020 a reference field doesn't resolve to a known artifact
PAC-030 a field value isn't in the type's allowed set (enums)
PAC-060 the committed generated bundle is missing or stale

Config reference

Each entry under types:

  • name — the collection name (and the key in the bundle).
  • dir — the subdirectory under product_dir.
  • id_prefix (optional) — required id prefix; with id_matches_filename (default true), the id must equal the filename stem.
  • required — frontmatter fields that must be present and non-empty (id always is).
  • fields — the fields captured into the bundle.
  • enumsfield -> [allowed values].
  • references[{ field, to }]: values of field must be the id of a to artifact.

Extending it — plugins

Real projects need more than schema: cross-file checks ("does this links.code path exist?"), derived bundle fields (reverse edges, rollups), extra generated outputs (a runtime catalogue), and their own diagnostic codes. A plugin registers those without forking the engine — which is how a large project migrates onto FastPDLC with no loss of functionality:

# product_hooks.py
from fastpdlc import register

def register(reg):
    register("PAC-900", "links.code path does not exist on disk")

    @reg.validator
    def code_paths_exist(bundle, config, root, report):
        for f in bundle["features"]:
            for path in f.get("code") or []:
                if not (root / path).exists():
                    report.add("PAC-900", f"missing {path}", f["_file"])

    @reg.bundle_transformer
    def reverse_edges(bundle, config, root):
        ...  # enrich the bundle in place

    reg.extra_output("build/catalogue.json", render_catalogue)  # staleness-gated too
fastpdlc -p product_hooks.py validate

Start a new repo in one command

Scaffold a ready-to-go product-as-code repo (config, example artifacts, and the CI gate) with the copier template:

pipx run copier copy --trust gh:tarvitave/fastpdlc my-product-repo

--trust lets the template run fastpdlc build once so the new repo is valid on its first commit.

CI

Use the reusable Action — it installs FastPDLC and runs the gate:

# .github/workflows/product.yml
name: product-as-code
on: [pull_request, push]
jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: tarvitave/fastpdlc@v0.1.0
        with:
          config: product.config.yaml     # optional (default)
          plugin: product_hooks.py         # optional project checks
Prefer plain pip?
      - uses: actions/setup-python@v5
        with: { python-version: "3.12" }
      - run: pip install fastpdlc
      - run: fastpdlc validate

Used in production

FastPDLC is the product-as-code engine of the pharthing / KibiPay payments platform (39 features, a concept catalogue, and a ~283 KB render bundle). pharthing's CI runs fastpdlc validate as its sole gate via a plugin that adds domain checks — a byte-identical parity test proves nothing was lost in the extraction. That's the plugin system above, doing real work.

Releasing

Publishing to PyPI is automated via GitHub Releases + Trusted Publishing — see RELEASING.md.

License

LGPL-3.0-or-later (copyleft, but you can import it as a library without your project inheriting the licence). See LICENSE.

Download files

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

Source Distribution

fastpdlc-0.1.0.tar.gz (17.7 kB view details)

Uploaded Source

Built Distribution

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

fastpdlc-0.1.0-py3-none-any.whl (15.3 kB view details)

Uploaded Python 3

File details

Details for the file fastpdlc-0.1.0.tar.gz.

File metadata

  • Download URL: fastpdlc-0.1.0.tar.gz
  • Upload date:
  • Size: 17.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fastpdlc-0.1.0.tar.gz
Algorithm Hash digest
SHA256 faf2b62aa47edca008033dcf2fe1aeb04c205e1728946c53e36cfd2b036a5b33
MD5 d58506ca20fd647bf176fc6ca4a8da3d
BLAKE2b-256 66c5a2f3426ea908c5aa03c2ff20a80d26f87feff84f59db0646b5bd12089b97

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastpdlc-0.1.0.tar.gz:

Publisher: publish.yml on tarvitave/fastpdlc

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastpdlc-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: fastpdlc-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fastpdlc-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a8d8b92ac280a7903ae23f23a261fc9512e7e746907cb3e731eac24ccde3333a
MD5 84efb2911b6c518cdd9fbbeab2dbc0d8
BLAKE2b-256 321d2be25eaabbf88bb3b155ce2f4589efd9dbdc4475cee846161d8da4e6c80a

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastpdlc-0.1.0-py3-none-any.whl:

Publisher: publish.yml on tarvitave/fastpdlc

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page