lcl-fastapi 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 (97) hide show
  1. lcl_fastapi-0.1.0/.gitignore +18 -0
  2. lcl_fastapi-0.1.0/AGENTS.md +255 -0
  3. lcl_fastapi-0.1.0/CHANGELOG.md +23 -0
  4. lcl_fastapi-0.1.0/LICENSE +21 -0
  5. lcl_fastapi-0.1.0/PKG-INFO +161 -0
  6. lcl_fastapi-0.1.0/README.md +132 -0
  7. lcl_fastapi-0.1.0/docs/application.md +82 -0
  8. lcl_fastapi-0.1.0/docs/cli.md +126 -0
  9. lcl_fastapi-0.1.0/docs/configuration.md +78 -0
  10. lcl_fastapi-0.1.0/docs/development-plan.md +211 -0
  11. lcl_fastapi-0.1.0/docs/engineering.md +46 -0
  12. lcl_fastapi-0.1.0/docs/features.md +31 -0
  13. lcl_fastapi-0.1.0/docs/health.md +93 -0
  14. lcl_fastapi-0.1.0/docs/linux.md +56 -0
  15. lcl_fastapi-0.1.0/docs/logging.md +81 -0
  16. lcl_fastapi-0.1.0/docs/nginx.md +49 -0
  17. lcl_fastapi-0.1.0/docs/releasing.md +60 -0
  18. lcl_fastapi-0.1.0/docs/runtime.md +119 -0
  19. lcl_fastapi-0.1.0/docs/systemd.md +58 -0
  20. lcl_fastapi-0.1.0/docs/windows.md +64 -0
  21. lcl_fastapi-0.1.0/examples/composed/.gitignore +5 -0
  22. lcl_fastapi-0.1.0/examples/composed/README.md +139 -0
  23. lcl_fastapi-0.1.0/examples/composed/catalog_service/__init__.py +1 -0
  24. lcl_fastapi-0.1.0/examples/composed/catalog_service/app.py +69 -0
  25. lcl_fastapi-0.1.0/examples/composed/pyproject.toml +13 -0
  26. lcl_fastapi-0.1.0/examples/composed/service.lclcfg +30 -0
  27. lcl_fastapi-0.1.0/examples/composed/verify.py +299 -0
  28. lcl_fastapi-0.1.0/examples/minimal/.gitignore +5 -0
  29. lcl_fastapi-0.1.0/examples/minimal/README.md +105 -0
  30. lcl_fastapi-0.1.0/examples/minimal/minimal_service/__init__.py +1 -0
  31. lcl_fastapi-0.1.0/examples/minimal/minimal_service/app.py +37 -0
  32. lcl_fastapi-0.1.0/examples/minimal/pyproject.toml +13 -0
  33. lcl_fastapi-0.1.0/examples/minimal/render.lclcfg +15 -0
  34. lcl_fastapi-0.1.0/examples/minimal/service.lclcfg +10 -0
  35. lcl_fastapi-0.1.0/examples/minimal/verify.py +266 -0
  36. lcl_fastapi-0.1.0/lcl-fastapi spec.md +1573 -0
  37. lcl_fastapi-0.1.0/pyproject.toml +98 -0
  38. lcl_fastapi-0.1.0/scripts/__init__.py +1 -0
  39. lcl_fastapi-0.1.0/scripts/architecture.py +87 -0
  40. lcl_fastapi-0.1.0/scripts/artifacts.py +85 -0
  41. lcl_fastapi-0.1.0/scripts/coverage_report.py +27 -0
  42. lcl_fastapi-0.1.0/scripts/documentation.py +61 -0
  43. lcl_fastapi-0.1.0/scripts/policy.py +105 -0
  44. lcl_fastapi-0.1.0/scripts/quality.py +77 -0
  45. lcl_fastapi-0.1.0/scripts/release.py +181 -0
  46. lcl_fastapi-0.1.0/scripts/verify_example.py +69 -0
  47. lcl_fastapi-0.1.0/src/lcl_fastapi/__init__.py +8 -0
  48. lcl_fastapi-0.1.0/src/lcl_fastapi/cli/__init__.py +5 -0
  49. lcl_fastapi-0.1.0/src/lcl_fastapi/cli/arguments.py +35 -0
  50. lcl_fastapi-0.1.0/src/lcl_fastapi/cli/commands.py +148 -0
  51. lcl_fastapi-0.1.0/src/lcl_fastapi/cli/main.py +41 -0
  52. lcl_fastapi-0.1.0/src/lcl_fastapi/cli/output.py +34 -0
  53. lcl_fastapi-0.1.0/src/lcl_fastapi/config.py +277 -0
  54. lcl_fastapi-0.1.0/src/lcl_fastapi/context.py +50 -0
  55. lcl_fastapi-0.1.0/src/lcl_fastapi/docs/__init__.py +1 -0
  56. lcl_fastapi-0.1.0/src/lcl_fastapi/docs/swagger.py +62 -0
  57. lcl_fastapi-0.1.0/src/lcl_fastapi/health/__init__.py +1 -0
  58. lcl_fastapi-0.1.0/src/lcl_fastapi/health/sampler.py +178 -0
  59. lcl_fastapi-0.1.0/src/lcl_fastapi/logging.py +103 -0
  60. lcl_fastapi-0.1.0/src/lcl_fastapi/middleware/__init__.py +1 -0
  61. lcl_fastapi-0.1.0/src/lcl_fastapi/middleware/request_context.py +117 -0
  62. lcl_fastapi-0.1.0/src/lcl_fastapi/py.typed +0 -0
  63. lcl_fastapi-0.1.0/src/lcl_fastapi/render/__init__.py +6 -0
  64. lcl_fastapi-0.1.0/src/lcl_fastapi/render/config.py +86 -0
  65. lcl_fastapi-0.1.0/src/lcl_fastapi/render/nginx.py +80 -0
  66. lcl_fastapi-0.1.0/src/lcl_fastapi/render/systemd.py +92 -0
  67. lcl_fastapi-0.1.0/src/lcl_fastapi/render/validation.py +60 -0
  68. lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/__init__.py +3 -0
  69. lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/access.py +30 -0
  70. lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/application.py +41 -0
  71. lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/common.py +149 -0
  72. lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/lease.py +64 -0
  73. lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/linux.py +129 -0
  74. lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/service.py +87 -0
  75. lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/state.py +123 -0
  76. lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/windows.py +108 -0
  77. lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/worker.py +175 -0
  78. lcl_fastapi-0.1.0/src/lcl_fastapi/service.py +206 -0
  79. lcl_fastapi-0.1.0/src/lcl_fastapi/static/defaults.lclcfg +30 -0
  80. lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/LICENSE +202 -0
  81. lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/NOTICE +2 -0
  82. lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/NOTICE.md +25 -0
  83. lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/favicon-32x32.png +0 -0
  84. lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/swagger-ui-bundle.js +2 -0
  85. lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/swagger-ui-bundle.js.LICENSE.txt +104 -0
  86. lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/swagger-ui.css +3 -0
  87. lcl_fastapi-0.1.0/tests/runtime_app.py +42 -0
  88. lcl_fastapi-0.1.0/tests/test_application.py +426 -0
  89. lcl_fastapi-0.1.0/tests/test_cli.py +210 -0
  90. lcl_fastapi-0.1.0/tests/test_documentation.py +34 -0
  91. lcl_fastapi-0.1.0/tests/test_health.py +199 -0
  92. lcl_fastapi-0.1.0/tests/test_release.py +203 -0
  93. lcl_fastapi-0.1.0/tests/test_render.py +151 -0
  94. lcl_fastapi-0.1.0/tests/test_render_documentation.py +17 -0
  95. lcl_fastapi-0.1.0/tests/test_runtime_operations.py +317 -0
  96. lcl_fastapi-0.1.0/tests/test_runtime_process.py +314 -0
  97. lcl_fastapi-0.1.0/tests/test_runtime_state.py +212 -0
@@ -0,0 +1,18 @@
1
+ venv/
2
+ .venv/
3
+ __pycache__/
4
+ *.py[cod]
5
+ *.egg-info/
6
+ .pytest_cache/
7
+ pytest-cache-files-*/
8
+ .mypy_cache/
9
+ .ruff_cache/
10
+ .coverage*
11
+ htmlcov/
12
+ reports/
13
+ dist/
14
+ build/
15
+ run/
16
+ logs/
17
+ *.log
18
+ .DS_Store
@@ -0,0 +1,255 @@
1
+ # lcl-fastapi project facts
2
+
3
+ This repository implements the reviewed `lcl-fastapi spec.md`. Development discussions may be Chinese; public documentation and production docstrings are English.
4
+
5
+ - Distribution: `lcl-fastapi`; import package: `lcl_fastapi`; production root: `src/lcl_fastapi`.
6
+ - License: MIT. Python metadata requires >=3.14; the initial target validation matrix is CPython 3.14 on Windows and Linux. Future versions are not claimed as tested.
7
+ - Runtime dependencies: lclang==1.0.10, FastAPI >=0.141,<0.142, Uvicorn >=0.52,<0.53, psutil >=7.2,<8, Winloop ==0.6.3 on Windows only, and Gunicorn >=26,<27 on Linux only. Use lclang.cli; argparse, Click and Typer are not allowed.
8
+ - Configuration comes from .lclcfg. The reviewed specification governs actual key names and semantics, including the complete public origin. Use lclang's formal logger settings and Snowflake implementation.
9
+ - Default branch: main; persistent publication branch: release; feature prefix: codex/. The user has authorized reviewing and squash-merging the implementation PR, then publishing the first 0.1.0 release through CI to PyPI and GitHub. Keep main and release; clean up the completed feature branch only after verified publication.
10
+ - This was an empty GitHub repository. An empty main bootstrap commit may establish a PR base. All product changes belong in the implementation PR.
11
+ - Version authority: pyproject.toml; any runtime version uses installed distribution metadata.
12
+ - Authoritative quality command: `venv/Scripts/python.exe -m scripts.quality` on Windows and `venv/bin/python -m scripts.quality` on Linux. The quality entry point, structural production policy, architecture, documentation/link, artifact-integrity checks, and cross-platform coverage CI are implemented. Semantic policy compliance requires review. Full compliance is established by the latest PR head's Windows/Linux jobs and strict aggregate coverage report, not by the presence of configured checks.
13
+ - Expected documentation entries: README.md, docs/development-plan.md, reference and guide pages under docs/. Examples are independent downstream projects and must not enter the wheel.
14
+ - Platform-specific real-process tests run on their respective operating systems. Combine Windows/Linux coverage data to enforce 100% production branch coverage without excluding platform modules.
15
+ - Agents share a workspace. Respect assigned file ownership and coordinate shared files before editing. Follow the user's current delegation instructions; the remaining work in this task is performed by the primary agent without subagents.
16
+ # Python project engineering requirements
17
+
18
+ ## Scope, project facts, and sources of truth
19
+
20
+ These requirements govern engineering quality and delivery. Keep the project's
21
+ business purpose, domain model, public behavior, and specialized architecture
22
+ in their existing sections. Read AGENTS.md, README.md, pyproject.toml, the
23
+ feature/status inventory if present, and relevant reference/development
24
+ documentation before changing code.
25
+
26
+ Record the actual distribution/import names, production source root, supported
27
+ Python versions and platforms, license, dependency policy, version source,
28
+ default branch, release branch, quality command, and documentation entry points.
29
+ Use pyproject.toml for packaging/tool metadata. Resolve license and compatibility
30
+ decisions from the project's choices; do not assume a license, Python minimum,
31
+ fixed version series, or release destination.
32
+
33
+ Reference documentation owns public contracts; executable guides own workflows;
34
+ tests own behavioral evidence; the feature inventory and README describe
35
+ implemented capability. The changelog records user-visible changes. Requirements
36
+ are not evidence of compliance: identify missing enforcement or documentation
37
+ without claiming that it already exists.
38
+
39
+ ## Design and public API
40
+
41
+ - Organize production code into small packages by responsibility. Dependencies
42
+ flow toward core types and domain logic; CLI, filesystem, network, and other
43
+ adapters depend on the core. Avoid cyclic imports and cross-layer shortcuts.
44
+ Package __init__.py files curate re-exports without behavioral initialization.
45
+ - Prefer the standard library and existing project mechanisms. Keep runtime
46
+ dependencies minimal and separate development, documentation, build, and
47
+ publishing dependencies. Do not introduce speculative abstractions or new
48
+ backends without a concrete requirement; preserve explicitly chosen native
49
+ integrations or dependencies.
50
+ - Design typed public APIs with explicit input validation, stable result/error
51
+ contracts, and documented compatibility. Use __all__ to curate exports and
52
+ ship py.typed for typed distributions. Distinguish intentional exceptions
53
+ from unexpected failures; preserve causes and useful context.
54
+ - For asynchronous I/O and resource workflows, prefer async public entry points.
55
+ Keep synchronous convenience boundaries explicit and prevent nested event
56
+ loops. Pure calculations need not become async merely for uniformity.
57
+ - Define resource ownership, cleanup order, cancellation behavior, and allowed
58
+ concurrency scope. Close caller-owned resources explicitly or through context
59
+ managers. Document whether objects are task-, thread-, or process-safe.
60
+ Specify cache consistency and recalculation/invalidation rules where caching
61
+ exists; do not import another project's cache semantics by default.
62
+ - State the actual trust boundary. Do not describe trusted configuration or
63
+ static capability checks as a hostile-code sandbox. Dynamic execution,
64
+ reflection, imports, ambient I/O, and connectivity need an explicit role in
65
+ the design rather than appearing accidentally through convenience helpers.
66
+
67
+ ## Production source requirements
68
+
69
+ - Each production Python file has at most 200 code-bearing physical lines,
70
+ excluding imports, declaration/attribute docstrings, pure comments, and blank
71
+ lines. Multiline signatures, expressions, and runtime strings count by their
72
+ physical lines. Do not compress statements or embed code in strings to evade
73
+ the limit. Split by responsibility, not arbitrary line count.
74
+ - Production functions and classes use descriptive names without an underscore
75
+ prefix. Only required Python protocol methods use dunder spellings. Do not
76
+ replace meaningful names with generic internal prefixes; curate exports with
77
+ __all__. These declaration rules do not forbid ordinary private state fields.
78
+ - Every production docstring is English rST. Functions and methods, including
79
+ nested helpers, explain how they work, every parameter with :param name:,
80
+ returned values with :returns: unless returning no value, and intentional
81
+ escaping exceptions with :raises Type:. Value classes document constructor
82
+ fields and edge cases. Use notes for useful special behavior, not repetition.
83
+ - Document every named constant and coherent constant group, including enums:
84
+ units or absence of units, actual source, purpose, and choice rationale.
85
+ Never invent external sources or annotate every ordinary control-flow literal.
86
+ - These size, naming, docstring, and constant requirements apply to production
87
+ source. Tests and scripts still pass Ruff and strict mypy. Existing explicit
88
+ project exceptions must be recorded rather than silently broadened.
89
+
90
+ ## Behavioral tests and isolation
91
+
92
+ - Mirror production subsystem responsibilities in tests. A test file may cover
93
+ several related implementation modules; each behavior has one obvious owner.
94
+ Keep integration contracts explicit and reusable fixtures in support modules
95
+ when actually shared. Do not require one test file per source file.
96
+ - Assert public behavior, observable state, and meaningful diagnostics rather
97
+ than private method calls or a second implementation of the same algorithm.
98
+ Cover sunny, rainy, boundary, and composite cases where applicable.
99
+ - Unit tests mock external connectivity, clocks, randomness, and other
100
+ nondeterminism as needed. Isolate file I/O and enabled logs in a separate
101
+ TemporaryDirectory per test. CLI test configuration sources are static
102
+ fixtures declared with their cases. No test should depend on a live account.
103
+ - Include deterministic stress, concurrency, cancellation, and lifecycle/leak
104
+ tests for relevant behavior in the ordinary full gate. Use property or
105
+ differential tests where there is a useful invariant or independent oracle.
106
+ Keep performance benchmarks separate from correctness acceptance.
107
+ - Require 100% production branch coverage, with no threshold reductions,
108
+ exclusions, ignores, weakened assertions, or invented skips merely to pass.
109
+ Report genuine platform/dependency skips explicitly and cover supported
110
+ platforms in the appropriate environment. Use strict test markers/config.
111
+ - If filesystem or temporary-directory permissions block a tool or test, stop
112
+ that operation and obtain the required permission. Do not relocate temporary
113
+ files, change temporary environment variables, weaken isolation, skip checks,
114
+ or change paths solely to bypass the restriction. Continue independent work.
115
+
116
+ ## Change workflow and quality gate
117
+
118
+ - For a bug: update the relevant English contract; add a behavioral regression
119
+ test and prove the intended failure; implement the smallest correct fix;
120
+ prove the test passes; refactor if needed and run focused/full checks.
121
+ - For a feature: prototypes may precede the settled contract, but acceptance
122
+ requires reference documentation and behavioral tests. Update README,
123
+ changelog, and the feature inventory when public claims change.
124
+ - For a refactor: pass existing tests first, change production code, pass the
125
+ same tests, then reorganize test ownership and verify again.
126
+ - Use one authoritative, reproducible quality entry point, preferably
127
+ python -m scripts.quality if no project equivalent exists. Define its concrete
128
+ command and environment in this file; identify it as required but unimplemented
129
+ if it does not exist yet.
130
+ - The gate fails fast through whitespace validation, Ruff, production-policy
131
+ checks, architecture/capability checks, strict mypy over source/tests/scripts,
132
+ documentation checks without coverage, and full behavioral tests with branch
133
+ coverage, including stress tests. Keep all checks in the same environment.
134
+ - Run affected checks during editing. Each completed code-refactor stage and
135
+ final code handoff runs the full gate. Re-run after new changes, failures, or
136
+ unresolved concerns; do not repeat unchanged successful suites without cause.
137
+ - Pure prose needs relevant structure and link checks. Execute the exact source
138
+ of changed examples. Structural documentation changes run the documentation
139
+ suite once without coverage; avoid chapter/series/full-gate duplication.
140
+ - Produce useful JUnit and machine-readable/browsable coverage reports when
141
+ supported. Keep generated reports ignored. Record actual commands, results,
142
+ skips, and tested revisions; never equate configured checks with passing ones.
143
+
144
+ ## Documentation and tutorials
145
+
146
+ - Keep public documentation in English with reference contracts, practical
147
+ guides, an accessible README, and a concise implemented-feature inventory.
148
+ Explain behavior and limitations; never present plans as implemented features.
149
+ - Each tutorial series has a useful standalone introduction and one ordered
150
+ table of contents. Link every published chapter; do not list planned chapters
151
+ as available or duplicate the inventory in other documentation entry points.
152
+ Use stable ordered topic filenames, such as NN-topic-name.md.
153
+ - Mark every complete copyable Python example with a project-specific execution
154
+ marker, using `<!-- python-doc-exec -->` when no marker exists. Documentation
155
+ tests extract and execute that exact Markdown source, not a copied equivalent.
156
+ - Teach the smallest useful operation first, add one concept at a time, and end
157
+ with a realistic composition. Put observable results in inline assertions
158
+ where practical. Explain why each result follows, what resolves or executes,
159
+ and who owns state; do not duplicate assertions in expected-result sections.
160
+ - Examples are deterministic and independent. Mock connectivity, isolate file
161
+ examples in TemporaryDirectory, and close async/resource scopes explicitly.
162
+ Examples must not use production credentials or persistent external effects.
163
+ - Test chapter discovery against the single table of contents and published
164
+ files. Update navigation and changelog when adding, renaming, reordering, or
165
+ retiring chapters. Do not impose word counts, slogans, one test per chapter,
166
+ or arbitrary exact example counts.
167
+ - Check relative links and anchors, CLI/API inventories, and executable snippets.
168
+ If a site/export exists, generate it from canonical Markdown after checks,
169
+ preserve exact examples, and validate navigation/assets. Avoid a competing
170
+ manually maintained copy of the same documentation.
171
+
172
+ ## Packaging and release integrity
173
+
174
+ - Declare build metadata, supported Python versions, license, project identity,
175
+ and tool settings in pyproject.toml. Keep a real license file and accurate
176
+ compatibility claims; do not silently change the license or support matrix.
177
+ - Keep one authoritative version source or verify all maintained copies agree,
178
+ including runtime __version__ when present. Respect established version and
179
+ tag conventions; for new projects use a documented PEP 440-compatible policy
180
+ with compatibility-aware version increments, not a fixed release series.
181
+ - Use isolated/reproducible build tooling appropriate to the project. Build a
182
+ wheel and source distribution from the verified release revision; include
183
+ production code, required runtime resources, typing data, packaging metadata,
184
+ license, and README. Keep local secrets, reports, environments, development
185
+ scratch files, and unrelated artifacts out of distributions.
186
+ - A release is a separate requested operation. Prepare a nonempty dated
187
+ changelog section for its version, retaining unreleased work separately.
188
+ Check notes and metadata before promotion. Preserve the selected source SHA
189
+ and artifact identity through the release; never silently replace a version's
190
+ published tag or distribution.
191
+ - Do not publish, push, merge, delete branches, or contact collaborators merely
192
+ because this policy was installed. Follow the authorized task scope, preserve
193
+ unrelated changes, and honor existing approvals without asking again.
194
+
195
+ ## GitHub feature delivery
196
+
197
+ Use issue -> feature branch -> pull request -> squash merge -> branch cleanup.
198
+
199
+ 1. Create or reuse an issue in the configured GitHub repository for authorized
200
+ feature/bug work. Record scope, public behavior, and acceptance criteria.
201
+ Fetch the configured remote and base a feature branch on the current default
202
+ branch. Prefer codex/<issue-number>-<description> unless the project uses an
203
+ explicit alternative.
204
+ 2. Keep implementation, tests, and documentation together. Follow the change
205
+ workflow and full gate, commit, push, and open a PR against the default
206
+ branch. Link the issue with Closes #number. Describe the final behavior,
207
+ material limitations, and actual verification results.
208
+ 3. Wait for all applicable checks on the exact latest PR head, including push
209
+ and PR verification/builds. Honor required reviews and branch rules. Fix
210
+ failures and re-check the updated head; earlier green checks do not approve
211
+ new commits. Intentional workflow-condition exclusions are not missing
212
+ checks. Keep PR metadata current.
213
+ 4. When merging is within scope, squash merge with an expected-head-SHA guard.
214
+ Preserve draft/review-only requests. Confirm merge and issue closure.
215
+ Synchronize the local default branch and confirm the merged content.
216
+ 5. Verify no post-review work remains on the feature branch before deleting
217
+ its remote and local copies. Squash merges lose feature-commit ancestry;
218
+ inspect merged content before a necessary forced local deletion. Finish
219
+ on the default branch without discarding unrelated work.
220
+
221
+ ## GitHub version publication
222
+
223
+ Use version update -> verified PR -> squash merge -> fast-forward release
224
+ -> CI quality/build -> PyPI -> matching Git tag and GitHub Release.
225
+
226
+ 1. On a feature or dedicated release-preparation branch, update the canonical
227
+ version and all maintained copies, including runtime metadata. Finalize a
228
+ dated changelog section. Validate notes, run the full gate, and verify the
229
+ latest PR's CI before squash merging.
230
+ 2. Select the verified merged commit on the default branch. Fast-forward the
231
+ persistent release branch to exactly that commit and push it. Never add
232
+ release-only commits, force the release branch, or publish a feature head.
233
+ 3. The configured release workflow verifies version notes and default-branch
234
+ ancestry, runs the full gate, builds distributions, and publishes those
235
+ artifacts to PyPI with Trusted Publishing. Use least-privilege permissions,
236
+ an appropriate publishing environment, and serialized uploads.
237
+ 4. After PyPI succeeds, CI creates the matching version tag and GitHub Release
238
+ at the same source commit with changelog notes and the same wheel/source
239
+ artifacts attached. Follow the configured tag format; for a new project,
240
+ use the exact version without a v prefix. Avoid a competing manual release.
241
+ 5. Verify completion, not dispatch: latest applicable CI results, successful
242
+ registry publication, tag target, published Release, attached artifacts, and
243
+ any applicable documentation deployment. Fetch the tag and report links.
244
+ If PyPI succeeds and Release creation fails, retry only the failed final
245
+ stage; never repeat a successful immutable-version upload. After uncertain
246
+ publication, inspect remote state before any retry.
247
+ 6. Keep the default and release branches. For a combined feature/release task,
248
+ clean up the implementation branch only after publication succeeds and
249
+ verification shows no unmerged work remains.
250
+
251
+ Apply this pipeline only when publication is part of the project and requested
252
+ task. A package deliberately not published to PyPI must state its actual release
253
+ destination instead. Missing credentials, environments, CI workflows, or required
254
+ approvals are concrete blockers to the affected stage; do not bypass branch or
255
+ registry controls or claim a release succeeded.
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ No unreleased changes.
6
+
7
+ ## 0.1.0 - 2026-09-11
8
+
9
+ - Add a typed LCL-powered FastAPI application with native Router and lifespan composition.
10
+ - Add server-generated request IDs, contextual logging, health sampling, and offline Swagger UI.
11
+ - Return HTTP 503 with one failure access log when the upstream Snowflake generator
12
+ reports clock rollback or sequence exhaustion; do not fabricate a fallback ID.
13
+ - Add Windows Uvicorn and Linux Gunicorn runtimes with local status, log-path, and graceful-stop commands.
14
+ - Propagate application import, configuration, and lifespan startup failures to a
15
+ nonzero service exit after native worker cleanup on both platforms.
16
+ - Keep master state, control tokens, and POSIX locks owned by their creating
17
+ process when a forked worker exits and is replaced.
18
+ - Publish worker observations outside the HTTP event loop and wait for active
19
+ writes before releasing worker resources during shutdown.
20
+ - Use Uvicorn's Winloop integration on Windows so every idle worker keeps publishing
21
+ observations after startup and replacement without new HTTP connections.
22
+ - Add Nginx and systemd configuration renderers that produce files without performing deployment operations.
23
+ - Establish executable documentation, independent downstream examples, and cross-platform engineering checks.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 gokurakujoudo
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,161 @@
1
+ Metadata-Version: 2.5
2
+ Name: lcl-fastapi
3
+ Version: 0.1.0
4
+ Summary: A lightweight LCL-powered FastAPI service framework
5
+ Project-URL: Repository, https://github.com/gokurakujoudo/lcl-fastapi
6
+ Project-URL: Issues, https://github.com/gokurakujoudo/lcl-fastapi/issues
7
+ Author: gokurakujoudo
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Requires-Python: >=3.14
11
+ Requires-Dist: fastapi<0.142,>=0.141
12
+ Requires-Dist: gunicorn<27,>=26; sys_platform == 'linux'
13
+ Requires-Dist: lclang==1.0.10
14
+ Requires-Dist: psutil<8,>=7.2
15
+ Requires-Dist: uvicorn<0.53,>=0.52
16
+ Requires-Dist: winloop==0.6.3; sys_platform == 'win32'
17
+ Provides-Extra: dev
18
+ Requires-Dist: build<2,>=1.2; extra == 'dev'
19
+ Requires-Dist: coverage[toml]<8,>=7.10; extra == 'dev'
20
+ Requires-Dist: hatchling<2,>=1.27; extra == 'dev'
21
+ Requires-Dist: httpx<1,>=0.28; extra == 'dev'
22
+ Requires-Dist: mypy<2,>=1.19; extra == 'dev'
23
+ Requires-Dist: pytest-asyncio<2,>=1.3; extra == 'dev'
24
+ Requires-Dist: pytest-cov<8,>=7; extra == 'dev'
25
+ Requires-Dist: pytest<10,>=9; extra == 'dev'
26
+ Requires-Dist: ruff<1,>=0.14; extra == 'dev'
27
+ Requires-Dist: types-psutil<8,>=7.2; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # lcl-fastapi
31
+
32
+ `lcl-fastapi` is a small Python 3.14+ service framework combining FastAPI with
33
+ `lclang==1.0.10` configuration, logging, CLI infrastructure, and Snowflake IDs.
34
+ Write business routes, a trusted `.lclcfg` file, and an optional business lifespan.
35
+ The framework owns worker startup, request IDs, health sampling, local operations,
36
+ and bundled offline Swagger UI.
37
+
38
+ Install the first release with `python -m pip install lcl-fastapi==0.1.0` in a
39
+ Python 3.14 virtual environment. See the [release process](docs/releasing.md)
40
+ for version notes, publication requirements, and artifact verification.
41
+
42
+ ## Start a service
43
+
44
+ Use a Python 3.14+ virtual environment. Install the built artifact with
45
+ `python -m pip install path/to/lcl_fastapi-0.1.0-py3-none-any.whl`. Dependencies must
46
+ also be installed; offline Swagger means that documentation serving does not
47
+ require a CDN after installation.
48
+
49
+ Save this application as `app.py` in your downstream project:
50
+
51
+ <!-- python-doc-exec -->
52
+ ```python
53
+ from lcl_fastapi import LclFastAPI, get_logger
54
+
55
+ service = LclFastAPI()
56
+
57
+
58
+ @service.get("/hello")
59
+ async def hello() -> dict[str, str]:
60
+ logger = await get_logger(__name__)
61
+ logger.info("hello requested")
62
+ return {"message": "hello"}
63
+ ```
64
+
65
+ Save `service.lclcfg` alongside it:
66
+
67
+ ```text
68
+ __LCL_VERSION__: 1
69
+ app.name: "example-service"
70
+ app.version: "1.0.0"
71
+ app.target: "app:service"
72
+ server.host: "127.0.0.1"
73
+ server.port: 8080
74
+ server.workers: 1
75
+ logger.file.default.directory: "./logs"
76
+ logger.file.service.filename: f"{app.name}.{worker_pid}.log"
77
+ logger.level: "INFO"
78
+ ```
79
+
80
+ From that project directory, run:
81
+
82
+ ```console
83
+ lcl-fastapi serve -o config service.lclcfg
84
+ ```
85
+
86
+ Open `http://127.0.0.1:8080/hello`, `/health`, or `/docs` in a browser. Swagger's
87
+ JavaScript, stylesheet, favicon, and OpenAPI schema are served locally. Its remote
88
+ validator is disabled. Responses normally carry a newly generated
89
+ `X-Request-ID`; incoming client IDs do not replace it. If the upstream generator
90
+ cannot issue an ID because of clock rollback or exhaustion, the response is 503
91
+ without a fabricated ID and the access log marks the failure. Business logs automatically
92
+ include the current ID, and each worker writes its own file.
93
+
94
+ Run operations in another terminal using the same configuration file:
95
+
96
+ ```console
97
+ lcl-fastapi status -o config service.lclcfg -o json
98
+ lcl-fastapi logs -o config service.lclcfg
99
+ lcl-fastapi stop -o config service.lclcfg
100
+ ```
101
+
102
+ The CLI deliberately follows `lclang.cli` syntax: `-o config`, not `-c` or
103
+ `--config`; `-o json`, not `--json`. Listener settings have no CLI overrides.
104
+ Log paths are the most recently published live-worker observations, so rollover
105
+ updates are eventually consistent. Stop uses a local control token and waits for
106
+ graceful termination, including business teardown and logger flush.
107
+
108
+ ## Application and deployment boundaries
109
+
110
+ Windows uses Uvicorn with automatically installed Winloop; Linux uses Gunicorn
111
+ to manage ASGI workers. You run the same
112
+ `lcl-fastapi serve` command on both. Only `127.0.0.1` and `0.0.0.0` are accepted
113
+ listener addresses; the default is loopback. Nginx can provide external HTTPS
114
+ and port forwarding, and systemd is optional. The render commands produce files
115
+ without installing them or running deployment commands.
116
+
117
+ Business Routers own their prefixes. There is no `api.prefix` setting.
118
+ `server.root_path` is optional external origin metadata such as
119
+ `https://api.example.com:8443`; it does not add a route prefix or set ASGI
120
+ `root_path`. Nginx's actual listener/TLS fields remain independent because a
121
+ public origin may describe an upstream proxy or port mapping.
122
+
123
+ The supported deployment scope is one service per machine. Configure separate
124
+ machines' Snowflake worker-ID ranges through LCL's environment-variable support.
125
+ Concurrent worker leases do not promise unlimited historical ID uniqueness
126
+ across crashes or rapid reuse. Do not edit configuration while the service is
127
+ running: a replacement worker reads the changed file while older workers retain
128
+ their original values. Use a complete externally managed restart for consistent
129
+ changes. There is no file watcher, hot restart, snapshot distribution, or restart
130
+ API.
131
+
132
+ User routes with the same HTTP method and exact path override built-in routes.
133
+ Overriding health or documentation replaces those defaults; overriding
134
+ `POST /_lcl/shutdown` can prevent the local stop command from working. The default
135
+ shutdown route is absent from OpenAPI and blocked by generated Nginx configuration.
136
+ There is no business authentication, management port, HTTP log endpoint, or log
137
+ streaming feature.
138
+
139
+ ## Documentation
140
+
141
+ Two independent downstream projects demonstrate the installed public package:
142
+ [minimal service](examples/minimal/README.md) and
143
+ [composed Router, configuration, and lifespan](examples/composed/README.md).
144
+ GitHub Actions builds the current source wheel, then installs that artifact and
145
+ each example in a separate environment on Windows/Uvicorn and Linux/Gunicorn.
146
+ Each run checks service availability, business and built-in HTTP APIs, all CLI
147
+ commands, and graceful shutdown. The example projects are excluded from the wheel.
148
+
149
+ - [Application and lifespan](docs/application.md)
150
+ - [Configuration](docs/configuration.md)
151
+ - [Request logging](docs/logging.md)
152
+ - [Health and observations](docs/health.md)
153
+ - [CLI reference](docs/cli.md)
154
+ - [Windows runtime](docs/windows.md) and [Linux runtime](docs/linux.md)
155
+ - [Nginx rendering](docs/nginx.md) and [systemd rendering](docs/systemd.md)
156
+ - [Development plan and acceptance evidence](docs/development-plan.md)
157
+ - [Implemented feature inventory](docs/features.md) and [engineering checks](docs/engineering.md)
158
+
159
+ The Python package is MIT-licensed. Bundled Swagger UI retains its Apache 2.0
160
+ license and third-party notices; see
161
+ [asset provenance](src/lcl_fastapi/static/swagger/NOTICE.md).
@@ -0,0 +1,132 @@
1
+ # lcl-fastapi
2
+
3
+ `lcl-fastapi` is a small Python 3.14+ service framework combining FastAPI with
4
+ `lclang==1.0.10` configuration, logging, CLI infrastructure, and Snowflake IDs.
5
+ Write business routes, a trusted `.lclcfg` file, and an optional business lifespan.
6
+ The framework owns worker startup, request IDs, health sampling, local operations,
7
+ and bundled offline Swagger UI.
8
+
9
+ Install the first release with `python -m pip install lcl-fastapi==0.1.0` in a
10
+ Python 3.14 virtual environment. See the [release process](docs/releasing.md)
11
+ for version notes, publication requirements, and artifact verification.
12
+
13
+ ## Start a service
14
+
15
+ Use a Python 3.14+ virtual environment. Install the built artifact with
16
+ `python -m pip install path/to/lcl_fastapi-0.1.0-py3-none-any.whl`. Dependencies must
17
+ also be installed; offline Swagger means that documentation serving does not
18
+ require a CDN after installation.
19
+
20
+ Save this application as `app.py` in your downstream project:
21
+
22
+ <!-- python-doc-exec -->
23
+ ```python
24
+ from lcl_fastapi import LclFastAPI, get_logger
25
+
26
+ service = LclFastAPI()
27
+
28
+
29
+ @service.get("/hello")
30
+ async def hello() -> dict[str, str]:
31
+ logger = await get_logger(__name__)
32
+ logger.info("hello requested")
33
+ return {"message": "hello"}
34
+ ```
35
+
36
+ Save `service.lclcfg` alongside it:
37
+
38
+ ```text
39
+ __LCL_VERSION__: 1
40
+ app.name: "example-service"
41
+ app.version: "1.0.0"
42
+ app.target: "app:service"
43
+ server.host: "127.0.0.1"
44
+ server.port: 8080
45
+ server.workers: 1
46
+ logger.file.default.directory: "./logs"
47
+ logger.file.service.filename: f"{app.name}.{worker_pid}.log"
48
+ logger.level: "INFO"
49
+ ```
50
+
51
+ From that project directory, run:
52
+
53
+ ```console
54
+ lcl-fastapi serve -o config service.lclcfg
55
+ ```
56
+
57
+ Open `http://127.0.0.1:8080/hello`, `/health`, or `/docs` in a browser. Swagger's
58
+ JavaScript, stylesheet, favicon, and OpenAPI schema are served locally. Its remote
59
+ validator is disabled. Responses normally carry a newly generated
60
+ `X-Request-ID`; incoming client IDs do not replace it. If the upstream generator
61
+ cannot issue an ID because of clock rollback or exhaustion, the response is 503
62
+ without a fabricated ID and the access log marks the failure. Business logs automatically
63
+ include the current ID, and each worker writes its own file.
64
+
65
+ Run operations in another terminal using the same configuration file:
66
+
67
+ ```console
68
+ lcl-fastapi status -o config service.lclcfg -o json
69
+ lcl-fastapi logs -o config service.lclcfg
70
+ lcl-fastapi stop -o config service.lclcfg
71
+ ```
72
+
73
+ The CLI deliberately follows `lclang.cli` syntax: `-o config`, not `-c` or
74
+ `--config`; `-o json`, not `--json`. Listener settings have no CLI overrides.
75
+ Log paths are the most recently published live-worker observations, so rollover
76
+ updates are eventually consistent. Stop uses a local control token and waits for
77
+ graceful termination, including business teardown and logger flush.
78
+
79
+ ## Application and deployment boundaries
80
+
81
+ Windows uses Uvicorn with automatically installed Winloop; Linux uses Gunicorn
82
+ to manage ASGI workers. You run the same
83
+ `lcl-fastapi serve` command on both. Only `127.0.0.1` and `0.0.0.0` are accepted
84
+ listener addresses; the default is loopback. Nginx can provide external HTTPS
85
+ and port forwarding, and systemd is optional. The render commands produce files
86
+ without installing them or running deployment commands.
87
+
88
+ Business Routers own their prefixes. There is no `api.prefix` setting.
89
+ `server.root_path` is optional external origin metadata such as
90
+ `https://api.example.com:8443`; it does not add a route prefix or set ASGI
91
+ `root_path`. Nginx's actual listener/TLS fields remain independent because a
92
+ public origin may describe an upstream proxy or port mapping.
93
+
94
+ The supported deployment scope is one service per machine. Configure separate
95
+ machines' Snowflake worker-ID ranges through LCL's environment-variable support.
96
+ Concurrent worker leases do not promise unlimited historical ID uniqueness
97
+ across crashes or rapid reuse. Do not edit configuration while the service is
98
+ running: a replacement worker reads the changed file while older workers retain
99
+ their original values. Use a complete externally managed restart for consistent
100
+ changes. There is no file watcher, hot restart, snapshot distribution, or restart
101
+ API.
102
+
103
+ User routes with the same HTTP method and exact path override built-in routes.
104
+ Overriding health or documentation replaces those defaults; overriding
105
+ `POST /_lcl/shutdown` can prevent the local stop command from working. The default
106
+ shutdown route is absent from OpenAPI and blocked by generated Nginx configuration.
107
+ There is no business authentication, management port, HTTP log endpoint, or log
108
+ streaming feature.
109
+
110
+ ## Documentation
111
+
112
+ Two independent downstream projects demonstrate the installed public package:
113
+ [minimal service](examples/minimal/README.md) and
114
+ [composed Router, configuration, and lifespan](examples/composed/README.md).
115
+ GitHub Actions builds the current source wheel, then installs that artifact and
116
+ each example in a separate environment on Windows/Uvicorn and Linux/Gunicorn.
117
+ Each run checks service availability, business and built-in HTTP APIs, all CLI
118
+ commands, and graceful shutdown. The example projects are excluded from the wheel.
119
+
120
+ - [Application and lifespan](docs/application.md)
121
+ - [Configuration](docs/configuration.md)
122
+ - [Request logging](docs/logging.md)
123
+ - [Health and observations](docs/health.md)
124
+ - [CLI reference](docs/cli.md)
125
+ - [Windows runtime](docs/windows.md) and [Linux runtime](docs/linux.md)
126
+ - [Nginx rendering](docs/nginx.md) and [systemd rendering](docs/systemd.md)
127
+ - [Development plan and acceptance evidence](docs/development-plan.md)
128
+ - [Implemented feature inventory](docs/features.md) and [engineering checks](docs/engineering.md)
129
+
130
+ The Python package is MIT-licensed. Bundled Swagger UI retains its Apache 2.0
131
+ license and third-party notices; see
132
+ [asset provenance](src/lcl_fastapi/static/swagger/NOTICE.md).