fabricgate 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. fabricgate-0.1.0/.editorconfig +25 -0
  2. fabricgate-0.1.0/.github/dependabot.yml +10 -0
  3. fabricgate-0.1.0/.github/workflows/ci.yaml +94 -0
  4. fabricgate-0.1.0/.github/workflows/release.yaml +165 -0
  5. fabricgate-0.1.0/.gitignore +68 -0
  6. fabricgate-0.1.0/.python-version +1 -0
  7. fabricgate-0.1.0/CONTRIBUTING.md +52 -0
  8. fabricgate-0.1.0/LICENSE +21 -0
  9. fabricgate-0.1.0/PKG-INFO +122 -0
  10. fabricgate-0.1.0/README.md +88 -0
  11. fabricgate-0.1.0/SECURITY.md +44 -0
  12. fabricgate-0.1.0/docs/contracts/CHANGELOG.md +85 -0
  13. fabricgate-0.1.0/docs/contracts/openapi.json +5963 -0
  14. fabricgate-0.1.0/docs/contracts/openapi.yaml +3968 -0
  15. fabricgate-0.1.0/docs/contracts/schemas/board-db.schema.json +154 -0
  16. fabricgate-0.1.0/docs/contracts/schemas/design-index.schema.json +221 -0
  17. fabricgate-0.1.0/docs/contracts/schemas/platform-manifest.schema.json +948 -0
  18. fabricgate-0.1.0/docs/specs/README.md +11 -0
  19. fabricgate-0.1.0/docs/specs/board-db-schema.md +198 -0
  20. fabricgate-0.1.0/docs/specs/cli-specification.md +1506 -0
  21. fabricgate-0.1.0/docs/specs/client-behavior.md +288 -0
  22. fabricgate-0.1.0/docs/specs/design-index-schema.md +282 -0
  23. fabricgate-0.1.0/docs/specs/platform-manifest-schema.md +679 -0
  24. fabricgate-0.1.0/pyproject.toml +102 -0
  25. fabricgate-0.1.0/scripts/extract_schemas.py +76 -0
  26. fabricgate-0.1.0/src/fabricgate/_version.py +4 -0
  27. fabricgate-0.1.0/src/fabricgate/cli/__init__.py +1 -0
  28. fabricgate-0.1.0/src/fabricgate/cli/commands/__init__.py +1 -0
  29. fabricgate-0.1.0/src/fabricgate/cli/commands/build.py +359 -0
  30. fabricgate-0.1.0/src/fabricgate/cli/commands/deprecate.py +77 -0
  31. fabricgate-0.1.0/src/fabricgate/cli/commands/diff.py +123 -0
  32. fabricgate-0.1.0/src/fabricgate/cli/commands/info.py +42 -0
  33. fabricgate-0.1.0/src/fabricgate/cli/commands/license_check.py +76 -0
  34. fabricgate-0.1.0/src/fabricgate/cli/commands/list_cmd.py +44 -0
  35. fabricgate-0.1.0/src/fabricgate/cli/commands/login.py +41 -0
  36. fabricgate-0.1.0/src/fabricgate/cli/commands/pull.py +80 -0
  37. fabricgate-0.1.0/src/fabricgate/cli/commands/push.py +162 -0
  38. fabricgate-0.1.0/src/fabricgate/cli/commands/quota.py +66 -0
  39. fabricgate-0.1.0/src/fabricgate/cli/commands/search.py +58 -0
  40. fabricgate-0.1.0/src/fabricgate/cli/commands/stats.py +95 -0
  41. fabricgate-0.1.0/src/fabricgate/cli/commands/token.py +106 -0
  42. fabricgate-0.1.0/src/fabricgate/cli/commands/verify.py +38 -0
  43. fabricgate-0.1.0/src/fabricgate/cli/commands/watch.py +58 -0
  44. fabricgate-0.1.0/src/fabricgate/cli/commands/webhook.py +166 -0
  45. fabricgate-0.1.0/src/fabricgate/cli/commands/yank.py +49 -0
  46. fabricgate-0.1.0/src/fabricgate/cli/exit_codes.py +28 -0
  47. fabricgate-0.1.0/src/fabricgate/cli/main.py +83 -0
  48. fabricgate-0.1.0/src/fabricgate/client/__init__.py +44 -0
  49. fabricgate-0.1.0/src/fabricgate/client/auth.py +108 -0
  50. fabricgate-0.1.0/src/fabricgate/client/cache.py +97 -0
  51. fabricgate-0.1.0/src/fabricgate/client/config.py +52 -0
  52. fabricgate-0.1.0/src/fabricgate/client/errors.py +27 -0
  53. fabricgate-0.1.0/src/fabricgate/client/publisher.py +147 -0
  54. fabricgate-0.1.0/src/fabricgate/client/puller.py +382 -0
  55. fabricgate-0.1.0/src/fabricgate/client/registry_client.py +649 -0
  56. fabricgate-0.1.0/src/fabricgate/client/resolver.py +93 -0
  57. fabricgate-0.1.0/src/fabricgate/client/validator.py +30 -0
  58. fabricgate-0.1.0/src/fabricgate/data/__init__.py +0 -0
  59. fabricgate-0.1.0/src/fabricgate/data/board-db/.gitkeep +0 -0
  60. fabricgate-0.1.0/src/fabricgate/data/board-db/official.yaml +79 -0
  61. fabricgate-0.1.0/src/fabricgate/models/__init__.py +10 -0
  62. fabricgate-0.1.0/src/fabricgate/models/api/__init__.py +1 -0
  63. fabricgate-0.1.0/src/fabricgate/models/api/errors.py +74 -0
  64. fabricgate-0.1.0/src/fabricgate/models/api/members.py +49 -0
  65. fabricgate-0.1.0/src/fabricgate/models/api/requests.py +211 -0
  66. fabricgate-0.1.0/src/fabricgate/models/api/responses.py +672 -0
  67. fabricgate-0.1.0/src/fabricgate/models/board_db.py +210 -0
  68. fabricgate-0.1.0/src/fabricgate/models/cli.py +312 -0
  69. fabricgate-0.1.0/src/fabricgate/models/common.py +390 -0
  70. fabricgate-0.1.0/src/fabricgate/models/design_index.py +110 -0
  71. fabricgate-0.1.0/src/fabricgate/models/platform_manifest.py +394 -0
  72. fabricgate-0.1.0/src/fabricgate/py.typed +1 -0
  73. fabricgate-0.1.0/src/fabricgate/sdk/__init__.py +5 -0
  74. fabricgate-0.1.0/src/fabricgate/sdk/_helpers.py +218 -0
  75. fabricgate-0.1.0/src/fabricgate/sdk/api.py +72 -0
  76. fabricgate-0.1.0/src/fabricgate/sdk/auth.py +231 -0
  77. fabricgate-0.1.0/src/fabricgate/sdk/designs/__init__.py +35 -0
  78. fabricgate-0.1.0/src/fabricgate/sdk/designs/diff.py +25 -0
  79. fabricgate-0.1.0/src/fabricgate/sdk/designs/license.py +69 -0
  80. fabricgate-0.1.0/src/fabricgate/sdk/designs/lifecycle.py +198 -0
  81. fabricgate-0.1.0/src/fabricgate/sdk/designs/pull.py +142 -0
  82. fabricgate-0.1.0/src/fabricgate/sdk/designs/push.py +163 -0
  83. fabricgate-0.1.0/src/fabricgate/sdk/designs/quota.py +41 -0
  84. fabricgate-0.1.0/src/fabricgate/sdk/designs/search.py +69 -0
  85. fabricgate-0.1.0/src/fabricgate/sdk/designs/stats.py +105 -0
  86. fabricgate-0.1.0/src/fabricgate/sdk/designs/watch.py +101 -0
  87. fabricgate-0.1.0/src/fabricgate/sdk/hwh_parser.py +152 -0
  88. fabricgate-0.1.0/src/fabricgate/sdk/webhooks.py +211 -0
  89. fabricgate-0.1.0/tests/__init__.py +0 -0
  90. fabricgate-0.1.0/tests/fixtures/__init__.py +5 -0
  91. fabricgate-0.1.0/tests/fixtures/demo_adder_design_index.yaml +23 -0
  92. fabricgate-0.1.0/tests/fixtures/demo_adder_platform_manifest.yaml +30 -0
  93. fabricgate-0.1.0/tests/fixtures/factory.py +63 -0
  94. fabricgate-0.1.0/tests/fixtures/hello_design_index.yaml +16 -0
  95. fabricgate-0.1.0/tests/fixtures/hello_platform_manifest.yaml +21 -0
  96. fabricgate-0.1.0/tests/fixtures/pynq_z2_shell_design_index.yaml +17 -0
  97. fabricgate-0.1.0/tests/fixtures/pynq_z2_shell_platform_manifest.yaml +25 -0
  98. fabricgate-0.1.0/tests/fixtures/sample_index.yaml +26 -0
  99. fabricgate-0.1.0/tests/fixtures/sample_manifest.yaml +21 -0
  100. fabricgate-0.1.0/tests/unit/__init__.py +0 -0
  101. fabricgate-0.1.0/tests/unit/test_cli.py +2822 -0
  102. fabricgate-0.1.0/tests/unit/test_client.py +566 -0
  103. fabricgate-0.1.0/tests/unit/test_client_errors.py +51 -0
  104. fabricgate-0.1.0/tests/unit/test_client_protocol.py +55 -0
  105. fabricgate-0.1.0/tests/unit/test_contract_schemas.py +109 -0
  106. fabricgate-0.1.0/tests/unit/test_extract_schemas.py +40 -0
  107. fabricgate-0.1.0/tests/unit/test_hwh_parser.py +617 -0
  108. fabricgate-0.1.0/tests/unit/test_models.py +2636 -0
  109. fabricgate-0.1.0/tests/unit/test_registry_client.py +993 -0
  110. fabricgate-0.1.0/tests/unit/test_release_hygiene.py +81 -0
  111. fabricgate-0.1.0/tests/unit/test_sdk.py +3970 -0
  112. fabricgate-0.1.0/tests/unit/test_watch.py +275 -0
  113. fabricgate-0.1.0/uv.lock +1873 -0
@@ -0,0 +1,25 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ insert_final_newline = true
7
+ trim_trailing_whitespace = true
8
+ indent_style = space
9
+ indent_size = 4
10
+
11
+ [*.{yaml,yml,json,toml}]
12
+ indent_size = 2
13
+
14
+ [*.{js,jsx,ts,tsx,css}]
15
+ indent_size = 2
16
+
17
+ [*.md]
18
+ trim_trailing_whitespace = false
19
+
20
+ [Makefile]
21
+ indent_style = tab
22
+
23
+ [Dockerfile*]
24
+ indent_style = space
25
+ indent_size = 4
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "uv"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ - package-ecosystem: "github-actions"
8
+ directory: "/"
9
+ schedule:
10
+ interval: "weekly"
@@ -0,0 +1,94 @@
1
+ name: CI
2
+
3
+ # Public CI: lint, type-check, unit tests, build + publication-boundary
4
+ # check, dependency audit. No secrets are used anywhere in this workflow.
5
+ on:
6
+ pull_request:
7
+ branches: [master]
8
+ push:
9
+ branches: [master]
10
+ workflow_call:
11
+ inputs:
12
+ force_all:
13
+ description: "Kept for release.yaml compatibility; every job always runs here"
14
+ type: boolean
15
+ default: false
16
+
17
+ permissions:
18
+ contents: read
19
+
20
+ jobs:
21
+ check:
22
+ name: Check (ruff / mypy)
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
26
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
27
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
28
+ with:
29
+ python-version-file: ".python-version"
30
+ - run: uv sync --frozen
31
+ - run: uv run ruff check .
32
+ - run: uv run ruff format --check .
33
+ - run: uv run mypy src
34
+
35
+ test:
36
+ name: Test
37
+ runs-on: ubuntu-latest
38
+ strategy:
39
+ matrix:
40
+ python-version: ["3.11", "3.12", "3.13"]
41
+ env:
42
+ # Overrides .python-version so both uv sync and uv run use the matrix
43
+ # interpreter; otherwise uv run re-creates the venv with 3.11 and drops
44
+ # the dev group.
45
+ UV_PYTHON: ${{ matrix.python-version }}
46
+ steps:
47
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
48
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
49
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
50
+ with:
51
+ python-version: ${{ matrix.python-version }}
52
+ - run: uv sync --frozen
53
+ - run: uv run pytest -q --cov=fabricgate --cov-report=term-missing
54
+
55
+ build:
56
+ name: Build & boundary check
57
+ runs-on: ubuntu-latest
58
+ steps:
59
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
60
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
61
+ - run: uv build
62
+ - name: Enforce publication boundary (no registry code in wheel/sdist)
63
+ run: |
64
+ set -euo pipefail
65
+ for whl in dist/*.whl; do
66
+ python3 -m zipfile --list "$whl" | grep -q "fabricgate/registry/" && { echo "::error::$whl contains fabricgate/registry/"; exit 1; }
67
+ done
68
+ for sdist in dist/*.tar.gz; do
69
+ tar -tzf "$sdist" | grep -q "fabricgate/registry/" && { echo "::error::$sdist contains fabricgate/registry/"; exit 1; }
70
+ done
71
+ echo "boundary OK"
72
+ - name: Smoke-install the wheel
73
+ run: |
74
+ python3 -m venv /tmp/smoke && /tmp/smoke/bin/pip install -q dist/*.whl
75
+ /tmp/smoke/bin/fabricgate --version && /tmp/smoke/bin/fgate --help > /dev/null
76
+
77
+ audit:
78
+ name: Dependency audit
79
+ runs-on: ubuntu-latest
80
+ steps:
81
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
82
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
83
+ - run: uv sync --frozen
84
+ - run: uv run pip-audit
85
+
86
+ ci-success:
87
+ name: CI Success
88
+ if: always()
89
+ needs: [check, test, build, audit]
90
+ runs-on: ubuntu-latest
91
+ steps:
92
+ - run: |
93
+ echo '${{ toJSON(needs) }}' | grep -qE '"result": "(failure|cancelled)"' && exit 1
94
+ echo "all green"
@@ -0,0 +1,165 @@
1
+ name: Release
2
+
3
+ # Triggers:
4
+ # - push of a stable vX.Y.Z tag: full release (PyPI + attestation + GitHub Release)
5
+ # Pre-release / staging tags (v0.1.0-staging.N) are handled by cd.yaml only;
6
+ # they would always fail the version guard below, so Release ignores them.
7
+ # - workflow_dispatch: TestPyPI dry-run (no GitHub Release)
8
+ #
9
+ # Prerequisites (one-time, human):
10
+ # - PyPI / TestPyPI Trusted Publisher registered for this repo
11
+ # (workflow=release.yaml, environment=pypi / testpypi)
12
+ # - GitHub environments `pypi` and `testpypi` created
13
+ on:
14
+ push:
15
+ tags:
16
+ - "v[0-9]+.[0-9]+.[0-9]+"
17
+ workflow_dispatch: # TestPyPI dry-run
18
+
19
+ concurrency:
20
+ group: release-${{ github.ref_name }}
21
+ cancel-in-progress: false
22
+
23
+ permissions:
24
+ contents: read
25
+
26
+ jobs:
27
+ ci:
28
+ name: CI Gate
29
+ # ci.yaml declares `pull-requests: read`; a called workflow cannot request
30
+ # more than the calling job holds, so grant it explicitly here. Without
31
+ # this GitHub refuses to start the run at all (startup_failure, 0 jobs).
32
+ permissions:
33
+ contents: read
34
+ pull-requests: read
35
+ uses: ./.github/workflows/ci.yaml
36
+ with:
37
+ # In reusable workflows the `github` context is the caller's, so
38
+ # ci.yaml's paths-filter sees an empty diff on tag pushes and would
39
+ # skip every job. Force the full gate instead.
40
+ force_all: true
41
+ secrets: inherit
42
+
43
+ build:
44
+ name: Build public package
45
+ runs-on: ubuntu-latest
46
+ needs: [ci]
47
+ steps:
48
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
49
+
50
+ - name: Install uv
51
+ uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
52
+
53
+ - name: Verify tag matches package version
54
+ if: github.event_name == 'push'
55
+ run: |
56
+ TAG_VERSION="${GITHUB_REF_NAME#v}"
57
+ PKG_VERSION=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
58
+ if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
59
+ echo "::error::tag v$TAG_VERSION != pyproject.toml version $PKG_VERSION"
60
+ exit 1
61
+ fi
62
+
63
+ - name: Use a unique dev version for TestPyPI dry-runs
64
+ # TestPyPI never lets a deleted filename be reused, so every dry-run
65
+ # publishes <version>.dev<run_number>. Tag pushes keep the real version.
66
+ if: github.event_name == 'workflow_dispatch'
67
+ run: |
68
+ set -euo pipefail
69
+ BASE=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
70
+ DEV="${BASE}.dev${GITHUB_RUN_NUMBER}"
71
+ uv version --frozen "$DEV"
72
+ sed -i "s/^__version__ = \".*\"$/__version__ = \"${DEV}\"/" src/fabricgate/_version.py
73
+ grep -q "\"${DEV}\"" src/fabricgate/_version.py
74
+ echo "dry-run version: ${DEV}"
75
+
76
+ - name: Build
77
+ run: uv build
78
+
79
+ - name: Enforce publication boundary (no registry code in wheel/sdist)
80
+ # Capture listings before grepping so a failed listing (missing
81
+ # artifact, unreadable archive) fails the step instead of being
82
+ # swallowed by the pipe inside the `if` condition.
83
+ run: |
84
+ set -euo pipefail
85
+ shopt -s nullglob
86
+ wheels=(dist/*.whl)
87
+ sdists=(dist/*.tar.gz)
88
+ if [ "${#wheels[@]}" -eq 0 ] || [ "${#sdists[@]}" -eq 0 ]; then
89
+ echo "::error::expected at least one wheel and one sdist in dist/ (found ${#wheels[@]} wheel(s), ${#sdists[@]} sdist(s))"
90
+ exit 1
91
+ fi
92
+ for whl in "${wheels[@]}"; do
93
+ listing=$(python3 -m zipfile --list "$whl")
94
+ if grep -q "fabricgate/registry/" <<<"$listing"; then
95
+ echo "::error::wheel $whl contains fabricgate/registry/ — distribution-policy P-2 violation"
96
+ exit 1
97
+ fi
98
+ done
99
+ for sdist in "${sdists[@]}"; do
100
+ listing=$(tar -tzf "$sdist")
101
+ if grep -q "fabricgate/registry/" <<<"$listing"; then
102
+ echo "::error::sdist $sdist contains fabricgate/registry/ — distribution-policy P-2 violation"
103
+ exit 1
104
+ fi
105
+ done
106
+
107
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
108
+ with:
109
+ name: dist
110
+ path: dist/
111
+
112
+ publish:
113
+ name: Publish to ${{ github.event_name == 'workflow_dispatch' && 'TestPyPI' || 'PyPI' }}
114
+ runs-on: ubuntu-latest
115
+ needs: [build]
116
+ environment: ${{ github.event_name == 'workflow_dispatch' && 'testpypi' || 'pypi' }}
117
+ permissions:
118
+ id-token: write # OIDC trusted publishing
119
+ attestations: write
120
+ contents: read
121
+ steps:
122
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
123
+ with:
124
+ name: dist
125
+ path: dist/
126
+
127
+ - name: Attest build provenance
128
+ # GitHub does not store attestations for user-owned *private* repos
129
+ # ("Feature not available for user-owned private repositories").
130
+ # Tolerate that on TestPyPI dry-runs so the publish path can still be
131
+ # rehearsed before the repo goes public; a real release (tag push)
132
+ # must ship provenance and therefore still fails loudly here.
133
+ continue-on-error: ${{ github.event_name == 'workflow_dispatch' }}
134
+ uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
135
+ with:
136
+ subject-path: "dist/*"
137
+
138
+ - name: Publish
139
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
140
+ with:
141
+ repository-url: ${{ github.event_name == 'workflow_dispatch' && 'https://test.pypi.org/legacy/' || 'https://upload.pypi.org/legacy/' }}
142
+ # TestPyPI rejects re-uploads of the same version; tolerate them
143
+ # on dry-runs only so repeated dispatches don't fail. Real PyPI
144
+ # releases (tag push) must still fail loudly on a duplicate.
145
+ skip-existing: ${{ github.event_name == 'workflow_dispatch' }}
146
+
147
+ release:
148
+ name: GitHub Release
149
+ if: github.event_name == 'push'
150
+ runs-on: ubuntu-latest
151
+ needs: [publish]
152
+ permissions:
153
+ contents: write
154
+ steps:
155
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
156
+
157
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
158
+ with:
159
+ name: dist
160
+ path: dist/
161
+
162
+ - name: Create GitHub Release
163
+ env:
164
+ GH_TOKEN: ${{ github.token }}
165
+ run: gh release create "$GITHUB_REF_NAME" --generate-notes dist/*
@@ -0,0 +1,68 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.egg
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ *.whl
11
+ .eggs/
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ ENV/
17
+
18
+ # Testing
19
+ .pytest_cache/
20
+ .coverage
21
+ coverage.xml
22
+ coverage.lcov
23
+ htmlcov/
24
+ .mypy_cache/
25
+
26
+ # IDE
27
+ .idea/
28
+ *.swp
29
+ *.swo
30
+ *~
31
+
32
+
33
+
34
+ # VSCode — keep shared settings, ignore user-specific files
35
+ .vscode/*
36
+ !.vscode/settings.json
37
+ !.vscode/extensions.json
38
+ !.vscode/launch.json
39
+ !.vscode/tasks.json
40
+
41
+ # Environment
42
+ .env
43
+ .env.local
44
+
45
+ # OS
46
+ .DS_Store
47
+ Thumbs.db
48
+
49
+ # Node.js (frontend)
50
+
51
+ # Alembic
52
+ *.db
53
+
54
+ # Docker
55
+ docker-compose.override.yaml
56
+ docker-compose.override.yml
57
+
58
+ # Local diagnostics
59
+ .diagnostics/
60
+ .vite/
61
+
62
+ # Project review reports
63
+ docs/report/
64
+ tmp/
65
+
66
+ # FPGA test fixture binaries (generated or downloaded — not committed)
67
+ tests/fixtures/binaries/
68
+ !tests/fixtures/binaries/.gitkeep
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,52 @@
1
+ # Contributing to FabricGate (CLI/SDK)
2
+
3
+ Thanks for your interest. This repository holds the public client side of FabricGate: the CLI, the Python SDK, the shared models and the API contracts. Bug reports, board additions, documentation fixes and features are all welcome.
4
+
5
+ ## Development setup
6
+
7
+ ```sh
8
+ git clone https://github.com/harurun78/fabricgate.git
9
+ cd fabricgate
10
+ uv sync # https://docs.astral.sh/uv/ (installs the dev group too)
11
+ uv run fabricgate --help
12
+ ```
13
+
14
+ Python 3.11+ is required. `uv.lock` is committed; CI installs with `--frozen`, so run `uv lock` when you change dependencies.
15
+
16
+ ## Checks that CI runs
17
+
18
+ ```sh
19
+ uv run ruff check .
20
+ uv run ruff format --check .
21
+ uv run mypy src
22
+ uv run pytest -q
23
+ uv build
24
+ ```
25
+
26
+ All of them must pass before a pull request is merged. Tests live in `tests/unit/`; fixtures in `tests/fixtures/`.
27
+
28
+ ## Changing the API contracts
29
+
30
+ `docs/contracts/` is the source of truth for the registry's public API. The wire-format JSON Schemas are generated from the models:
31
+
32
+ ```sh
33
+ uv run python scripts/extract_schemas.py
34
+ ```
35
+
36
+ Commit the regenerated files together with the model change and add an entry to `docs/contracts/CHANGELOG.md`. Breaking changes to the *read* API are not accepted without a migration note; the write API is still marked MVP and may change.
37
+
38
+ ## Adding a board to the Board DB
39
+
40
+ Boards live in `src/fabricgate/data/board-db/official.yaml` and are validated against `docs/contracts/schemas/board-db.schema.json` (`tests/unit/test_models.py`). Add an entry with `board_id`, `device`, the supported runtimes and a source URL for the identification data, and open a pull request. No code change is needed.
41
+
42
+ ## Pull requests
43
+
44
+ - One purpose per pull request; keep unrelated refactors out.
45
+ - Conventional Commits for titles (`feat(cli): ...`, `fix(sdk): ...`, `docs: ...`).
46
+ - Describe how you verified the change. Screenshots are not needed; command output is.
47
+ - Do not add secrets, tokens or personal data to tests, fixtures or CI. The workflows in this repository run without any secrets by design.
48
+ - Please reference issues from **this** repository only. The registry implementation is developed elsewhere; if a change here depends on a server-side change, describe it in words rather than linking an internal issue number.
49
+
50
+ ## Reporting bugs
51
+
52
+ Open an issue with the `fabricgate --version` output, the command you ran, and the full error text (`--verbose` helps). Security problems go to the address in [SECURITY.md](SECURITY.md), not to the issue tracker.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FabricGate Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,122 @@
1
+ Metadata-Version: 2.5
2
+ Name: fabricgate
3
+ Version: 0.1.0
4
+ Summary: FabricGate CLI/SDK — discover, pull and verify FPGA designs across boards and runtimes
5
+ Project-URL: Homepage, https://github.com/harurun78/fabricgate
6
+ Project-URL: Source, https://github.com/harurun78/fabricgate
7
+ Project-URL: Issues, https://github.com/harurun78/fabricgate/issues
8
+ Project-URL: Changelog, https://github.com/harurun78/fabricgate/blob/master/docs/contracts/CHANGELOG.md
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: bitstream,cli,fpga,pynq,registry
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Embedded Systems
21
+ Classifier: Topic :: System :: Hardware
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: click>=8.3.3
24
+ Requires-Dist: cryptography>=50.0.0
25
+ Requires-Dist: defusedxml>=0.7
26
+ Requires-Dist: email-validator>=2.2
27
+ Requires-Dist: httpx>=0.27
28
+ Requires-Dist: keyring>=25.0
29
+ Requires-Dist: pydantic-settings>=2.14.2
30
+ Requires-Dist: pydantic>=2.8
31
+ Requires-Dist: pyyaml>=6.0
32
+ Requires-Dist: rich>=13.7
33
+ Description-Content-Type: text/markdown
34
+
35
+ # FabricGate
36
+
37
+ [![CI](https://github.com/harurun78/fabricgate/actions/workflows/ci.yaml/badge.svg)](https://github.com/harurun78/fabricgate/actions/workflows/ci.yaml)
38
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
39
+
40
+ **Discover, pull and verify FPGA designs for your board — one command, any runtime.**
41
+
42
+ FabricGate is a package registry for FPGA designs (bitstreams plus the metadata a runtime needs to load them). This repository contains the client side: the `fabricgate` CLI, the Python SDK, the shared data models, and the public API contracts. The hosted registry lives at `https://registry.fabricgate.dev`.
43
+
44
+ > **Status: alpha.** The registry is being seeded with community PYNQ overlays. Interfaces marked *stable* in `docs/specs/` are kept backward compatible; everything else may still change before 1.0.
45
+
46
+ ## Install
47
+
48
+ ```sh
49
+ pip install fabricgate
50
+ ```
51
+
52
+ Python 3.11 or newer. `fgate` is installed as a short alias of `fabricgate`.
53
+
54
+ ## Three steps to a running design
55
+
56
+ ```sh
57
+ # 1. Find a design for your board
58
+ fabricgate search --platform pynq-z2/pynq adder
59
+
60
+ # 2. Pull it (bitstream + hwh + manifest, digests verified on download)
61
+ fabricgate pull example/adder-demo:1.0.0 --platform pynq-z2/pynq
62
+
63
+ # 3. Load it with the runtime you already use
64
+ python -c "from pynq import Overlay; ol = Overlay('adder-demo/adder.bit')"
65
+ ```
66
+
67
+ `example/adder-demo` is a placeholder name; run `fabricgate search` to see what is actually published. The `--platform` value is `<board>/<runtime>`; run `fabricgate pull --help` for the resolution rules, including the `generic-<device>` fallback.
68
+
69
+ ## What the CLI can do
70
+
71
+ | Command | Purpose |
72
+ |---|---|
73
+ | `search`, `info`, `diff`, `stats`, `watch` | discover designs and track updates |
74
+ | `pull`, `verify`, `list` | download with digest verification, re-verify, inspect the local cache |
75
+ | `build`, `push`, `yank`, `deprecate` | publish your own designs (`build` generates the Platform Manifest and Design Index from a build directory) |
76
+ | `login`, `token`, `quota`, `webhook`, `license-check` | account, automation and policy helpers |
77
+
78
+ `fabricgate --json` gives machine-readable output for every command.
79
+
80
+ ## Supported boards and runtimes
81
+
82
+ The bundled Board DB (`src/fabricgate/data/board-db/official.yaml`) currently knows these boards:
83
+
84
+ | Board | Device | Runtime |
85
+ |---|---|---|
86
+ | `pynq-z2` | xc7z020 | `pynq` |
87
+ | `zcu104` | xczu7ev | `pynq`, `linux-fpgamgr` |
88
+ | `pico-ice` | iCE40UP5K | `nanopynq` (Phase 3, forward reference) |
89
+ | `generic-xc7z020`, `generic-xczu7ev` | — | device-level fallback for boards not yet listed |
90
+
91
+ Adding a board is a data change; see [CONTRIBUTING.md](CONTRIBUTING.md).
92
+
93
+ ## SDK
94
+
95
+ ```python
96
+ from fabricgate.sdk import api
97
+
98
+ result = api.pull("example/adder-demo:1.0.0", platform="pynq-z2/pynq")
99
+ print(result.artifacts)
100
+ ```
101
+
102
+ The SDK wraps the same client the CLI uses. See `docs/specs/client-behavior.md` for the resolution and caching rules.
103
+
104
+ ## Public contracts
105
+
106
+ `docs/contracts/` is the source of truth for the registry's public API:
107
+
108
+ - `openapi.yaml` / `openapi.json` — Registry HTTP API
109
+ - `schemas/design-index.schema.json`, `schemas/platform-manifest.schema.json`, `schemas/board-db.schema.json` — wire formats
110
+ - `CHANGELOG.md` — contract changes and migration notes
111
+
112
+ Specifications for the CLI, client behaviour and data formats are in `docs/specs/`.
113
+
114
+ ## Self-hosting and the registry implementation
115
+
116
+ The registry server is operated as a hosted service and its implementation is not published at this stage (see `docs/specs/` for the distribution policy summary in `client-behavior.md`). Everything a client needs to interoperate — API, schemas, error formats — is in this repository, so alternative implementations are possible.
117
+
118
+ ## Contributing, security, license
119
+
120
+ - [CONTRIBUTING.md](CONTRIBUTING.md) — development setup, tests, pull requests
121
+ - [SECURITY.md](SECURITY.md) — how to report a vulnerability
122
+ - [LICENSE](LICENSE) — MIT
@@ -0,0 +1,88 @@
1
+ # FabricGate
2
+
3
+ [![CI](https://github.com/harurun78/fabricgate/actions/workflows/ci.yaml/badge.svg)](https://github.com/harurun78/fabricgate/actions/workflows/ci.yaml)
4
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
+
6
+ **Discover, pull and verify FPGA designs for your board — one command, any runtime.**
7
+
8
+ FabricGate is a package registry for FPGA designs (bitstreams plus the metadata a runtime needs to load them). This repository contains the client side: the `fabricgate` CLI, the Python SDK, the shared data models, and the public API contracts. The hosted registry lives at `https://registry.fabricgate.dev`.
9
+
10
+ > **Status: alpha.** The registry is being seeded with community PYNQ overlays. Interfaces marked *stable* in `docs/specs/` are kept backward compatible; everything else may still change before 1.0.
11
+
12
+ ## Install
13
+
14
+ ```sh
15
+ pip install fabricgate
16
+ ```
17
+
18
+ Python 3.11 or newer. `fgate` is installed as a short alias of `fabricgate`.
19
+
20
+ ## Three steps to a running design
21
+
22
+ ```sh
23
+ # 1. Find a design for your board
24
+ fabricgate search --platform pynq-z2/pynq adder
25
+
26
+ # 2. Pull it (bitstream + hwh + manifest, digests verified on download)
27
+ fabricgate pull example/adder-demo:1.0.0 --platform pynq-z2/pynq
28
+
29
+ # 3. Load it with the runtime you already use
30
+ python -c "from pynq import Overlay; ol = Overlay('adder-demo/adder.bit')"
31
+ ```
32
+
33
+ `example/adder-demo` is a placeholder name; run `fabricgate search` to see what is actually published. The `--platform` value is `<board>/<runtime>`; run `fabricgate pull --help` for the resolution rules, including the `generic-<device>` fallback.
34
+
35
+ ## What the CLI can do
36
+
37
+ | Command | Purpose |
38
+ |---|---|
39
+ | `search`, `info`, `diff`, `stats`, `watch` | discover designs and track updates |
40
+ | `pull`, `verify`, `list` | download with digest verification, re-verify, inspect the local cache |
41
+ | `build`, `push`, `yank`, `deprecate` | publish your own designs (`build` generates the Platform Manifest and Design Index from a build directory) |
42
+ | `login`, `token`, `quota`, `webhook`, `license-check` | account, automation and policy helpers |
43
+
44
+ `fabricgate --json` gives machine-readable output for every command.
45
+
46
+ ## Supported boards and runtimes
47
+
48
+ The bundled Board DB (`src/fabricgate/data/board-db/official.yaml`) currently knows these boards:
49
+
50
+ | Board | Device | Runtime |
51
+ |---|---|---|
52
+ | `pynq-z2` | xc7z020 | `pynq` |
53
+ | `zcu104` | xczu7ev | `pynq`, `linux-fpgamgr` |
54
+ | `pico-ice` | iCE40UP5K | `nanopynq` (Phase 3, forward reference) |
55
+ | `generic-xc7z020`, `generic-xczu7ev` | — | device-level fallback for boards not yet listed |
56
+
57
+ Adding a board is a data change; see [CONTRIBUTING.md](CONTRIBUTING.md).
58
+
59
+ ## SDK
60
+
61
+ ```python
62
+ from fabricgate.sdk import api
63
+
64
+ result = api.pull("example/adder-demo:1.0.0", platform="pynq-z2/pynq")
65
+ print(result.artifacts)
66
+ ```
67
+
68
+ The SDK wraps the same client the CLI uses. See `docs/specs/client-behavior.md` for the resolution and caching rules.
69
+
70
+ ## Public contracts
71
+
72
+ `docs/contracts/` is the source of truth for the registry's public API:
73
+
74
+ - `openapi.yaml` / `openapi.json` — Registry HTTP API
75
+ - `schemas/design-index.schema.json`, `schemas/platform-manifest.schema.json`, `schemas/board-db.schema.json` — wire formats
76
+ - `CHANGELOG.md` — contract changes and migration notes
77
+
78
+ Specifications for the CLI, client behaviour and data formats are in `docs/specs/`.
79
+
80
+ ## Self-hosting and the registry implementation
81
+
82
+ The registry server is operated as a hosted service and its implementation is not published at this stage (see `docs/specs/` for the distribution policy summary in `client-behavior.md`). Everything a client needs to interoperate — API, schemas, error formats — is in this repository, so alternative implementations are possible.
83
+
84
+ ## Contributing, security, license
85
+
86
+ - [CONTRIBUTING.md](CONTRIBUTING.md) — development setup, tests, pull requests
87
+ - [SECURITY.md](SECURITY.md) — how to report a vulnerability
88
+ - [LICENSE](LICENSE) — MIT