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.
- lcl_fastapi-0.1.0/.gitignore +18 -0
- lcl_fastapi-0.1.0/AGENTS.md +255 -0
- lcl_fastapi-0.1.0/CHANGELOG.md +23 -0
- lcl_fastapi-0.1.0/LICENSE +21 -0
- lcl_fastapi-0.1.0/PKG-INFO +161 -0
- lcl_fastapi-0.1.0/README.md +132 -0
- lcl_fastapi-0.1.0/docs/application.md +82 -0
- lcl_fastapi-0.1.0/docs/cli.md +126 -0
- lcl_fastapi-0.1.0/docs/configuration.md +78 -0
- lcl_fastapi-0.1.0/docs/development-plan.md +211 -0
- lcl_fastapi-0.1.0/docs/engineering.md +46 -0
- lcl_fastapi-0.1.0/docs/features.md +31 -0
- lcl_fastapi-0.1.0/docs/health.md +93 -0
- lcl_fastapi-0.1.0/docs/linux.md +56 -0
- lcl_fastapi-0.1.0/docs/logging.md +81 -0
- lcl_fastapi-0.1.0/docs/nginx.md +49 -0
- lcl_fastapi-0.1.0/docs/releasing.md +60 -0
- lcl_fastapi-0.1.0/docs/runtime.md +119 -0
- lcl_fastapi-0.1.0/docs/systemd.md +58 -0
- lcl_fastapi-0.1.0/docs/windows.md +64 -0
- lcl_fastapi-0.1.0/examples/composed/.gitignore +5 -0
- lcl_fastapi-0.1.0/examples/composed/README.md +139 -0
- lcl_fastapi-0.1.0/examples/composed/catalog_service/__init__.py +1 -0
- lcl_fastapi-0.1.0/examples/composed/catalog_service/app.py +69 -0
- lcl_fastapi-0.1.0/examples/composed/pyproject.toml +13 -0
- lcl_fastapi-0.1.0/examples/composed/service.lclcfg +30 -0
- lcl_fastapi-0.1.0/examples/composed/verify.py +299 -0
- lcl_fastapi-0.1.0/examples/minimal/.gitignore +5 -0
- lcl_fastapi-0.1.0/examples/minimal/README.md +105 -0
- lcl_fastapi-0.1.0/examples/minimal/minimal_service/__init__.py +1 -0
- lcl_fastapi-0.1.0/examples/minimal/minimal_service/app.py +37 -0
- lcl_fastapi-0.1.0/examples/minimal/pyproject.toml +13 -0
- lcl_fastapi-0.1.0/examples/minimal/render.lclcfg +15 -0
- lcl_fastapi-0.1.0/examples/minimal/service.lclcfg +10 -0
- lcl_fastapi-0.1.0/examples/minimal/verify.py +266 -0
- lcl_fastapi-0.1.0/lcl-fastapi spec.md +1573 -0
- lcl_fastapi-0.1.0/pyproject.toml +98 -0
- lcl_fastapi-0.1.0/scripts/__init__.py +1 -0
- lcl_fastapi-0.1.0/scripts/architecture.py +87 -0
- lcl_fastapi-0.1.0/scripts/artifacts.py +85 -0
- lcl_fastapi-0.1.0/scripts/coverage_report.py +27 -0
- lcl_fastapi-0.1.0/scripts/documentation.py +61 -0
- lcl_fastapi-0.1.0/scripts/policy.py +105 -0
- lcl_fastapi-0.1.0/scripts/quality.py +77 -0
- lcl_fastapi-0.1.0/scripts/release.py +181 -0
- lcl_fastapi-0.1.0/scripts/verify_example.py +69 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/__init__.py +8 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/cli/__init__.py +5 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/cli/arguments.py +35 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/cli/commands.py +148 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/cli/main.py +41 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/cli/output.py +34 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/config.py +277 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/context.py +50 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/docs/__init__.py +1 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/docs/swagger.py +62 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/health/__init__.py +1 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/health/sampler.py +178 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/logging.py +103 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/middleware/__init__.py +1 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/middleware/request_context.py +117 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/py.typed +0 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/render/__init__.py +6 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/render/config.py +86 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/render/nginx.py +80 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/render/systemd.py +92 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/render/validation.py +60 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/__init__.py +3 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/access.py +30 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/application.py +41 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/common.py +149 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/lease.py +64 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/linux.py +129 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/service.py +87 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/state.py +123 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/windows.py +108 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/runtime/worker.py +175 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/service.py +206 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/static/defaults.lclcfg +30 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/LICENSE +202 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/NOTICE +2 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/NOTICE.md +25 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/favicon-32x32.png +0 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/swagger-ui-bundle.js +2 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/swagger-ui-bundle.js.LICENSE.txt +104 -0
- lcl_fastapi-0.1.0/src/lcl_fastapi/static/swagger/swagger-ui.css +3 -0
- lcl_fastapi-0.1.0/tests/runtime_app.py +42 -0
- lcl_fastapi-0.1.0/tests/test_application.py +426 -0
- lcl_fastapi-0.1.0/tests/test_cli.py +210 -0
- lcl_fastapi-0.1.0/tests/test_documentation.py +34 -0
- lcl_fastapi-0.1.0/tests/test_health.py +199 -0
- lcl_fastapi-0.1.0/tests/test_release.py +203 -0
- lcl_fastapi-0.1.0/tests/test_render.py +151 -0
- lcl_fastapi-0.1.0/tests/test_render_documentation.py +17 -0
- lcl_fastapi-0.1.0/tests/test_runtime_operations.py +317 -0
- lcl_fastapi-0.1.0/tests/test_runtime_process.py +314 -0
- lcl_fastapi-0.1.0/tests/test_runtime_state.py +212 -0
|
@@ -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).
|