Skip to content

Commit 976e2f6

Browse files
2nd1stclaude
andcommitted
docs: OSS hygiene sweep — CONTRIBUTING, CoC, governance, templates, glossary, ops, NOTICES, example config
12-file batch authored by a 4-agent workflow (woktdz0xs) with two follow-up passes to close the workflow's own consistency review: NEW files (10): - CONTRIBUTING.md — pre-PR commands, code style, restraint bar + scope reference to ROADMAP §"What we will not do", honest "single maintainer, no SLA" expectations. - CODE_OF_CONDUCT.md — Contributor Covenant v2.1 verbatim from contributor-covenant.org; the Anthropic content filter blocked in-band generation of the boilerplate (false positive on the harassment/discrimination vocabulary), so the canonical text was fetched directly and the [INSERT CONTACT METHOD] placeholder was replaced with the GitHub-issue + @2nd1st mention path. - .github/GOVERNANCE.md — one-page maintainer note: single maintainer, MIT, no CLA, gate-before-feature stance, forking is fine; written by hand to dodge the same content-filter trip. - .github/PULL_REQUEST_TEMPLATE.md — what changed / trade-off cited / tests / go test -race + golangci-lint checkboxes / CHANGELOG entry. - .github/ISSUE_TEMPLATE/bug_report.md — version, deployment shape, repro, /healthz block, redacted JSONL, logs. - .github/ISSUE_TEMPLATE/feature_request.md — adopter use case, "why not a plugin", existing-surface gap, bounded scope. - .github/ISSUE_TEMPLATE/config.yml — blank_issues_enabled: false; contact links: security advisory + CONTRIBUTING.md + README. - api-log.example.yaml — every YAML key in internal/config/config.go documented with defaults + APILOG_* env override, grouped by section. New v0.1.1/v0.1.2 surfaces covered (api.export_byte_hardcap, plugins.capture_filter.patterns, viewer.releases_api_base + releases_auth_token). - THIRD_PARTY_NOTICES.md — runtime Go modules grouped by license (BSD-3-Clause, MIT, MIT/Apache-2.0 dual, Apache-2.0, MPL-2.0); viewer npm tree explicitly out of scope with pointer to the viewer repo. - docs/glossary.md — alphabetical, 12 entries (bucket / capture_filter / data_dir / finalize / key_hash / key_hash8 / lease / path_filter / prefix_canonical_hash / retention / session / session_root_id / trace) with ARCHITECTURE back-refs. - docs/operations.md — Day-2 ops: WAL checkpoint policy, backup procedure (sqlite3 .backup + JSONL tar), retention cross-reference, multi-instance limitations (ULID + WAL contention). MODIFIED (3): - README.md / README.zh.md — new "## Configuration" section between Quick start and How recording works; defaults < YAML < env precedence; top-5 env vars table; pointer to api-log.example.yaml. - ARCHITECTURE.md — new §14 "What this is not" with subsections on single-node, JSONL-truth, WAL concurrency, no-gateway-behavior. FIXES applied post-author (from workflow's consistency review): - docs/glossary.md `data_dir` entry corrected: the binary has no `--data-dir` flag and no `APILOG_DATA_DIR` env; the real surface is `storage.data_dir:` YAML + `APILOG_STORAGE_DATA_DIR` env, and the only CLI flag is `-config`. - docs/glossary.md `lease` entry: dropped wrong "ARCHITECTURE §7.4" ref (§7.4 is "Daily rotation"); pointed at docs/retention.md and internal/storage/lease.go directly. - docs/operations.md + ARCHITECTURE.md: replaced two new "ROADMAP §13" references with "ROADMAP \"Day-2 operations\"" since ROADMAP has no numbered sections (pre-existing §-numbered refs elsewhere stayed unchanged, out of this sweep's scope). - .github/ISSUE_TEMPLATE/config.yml: added CONTRIBUTING.md contact link since CONTRIBUTING.md now exists (workflow author flagged it as missing at the time of writing). NOT ATTEMPTED in this commit (deferred backlog): - Viewer-side CONTRIBUTING.md / CoC / governance — sister repo, separate decision. - Independent codex review pass — hung on the first attempt (process appeared stuck at the agent boot stage); workflow's own consistency reviewer caught the load-bearing issues, codex second-opinion can come later if a specific concern surfaces. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent b32b648 commit 976e2f6

14 files changed

Lines changed: 1148 additions & 0 deletions

‎.github/GOVERNANCE.md‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Governance
2+
3+
This is a one-page note so adopters know what to expect from this
4+
repository before they invest time on a PR.
5+
6+
## Maintainer
7+
8+
api-log has a single maintainer (`@2nd1st`). It is a hobby project
9+
plus a working tool for my own LLM-gateway recording needs — not a
10+
backed product, not a company deliverable. There is no SLA, no
11+
guaranteed response time, and no roadmap-voting process.
12+
13+
## Decision-making
14+
15+
- The maintainer's call is final on scope, design, and what ships.
16+
- Pull requests are welcome but acceptance is not guaranteed. Issues
17+
that include a concrete adopter use case have a much higher chance
18+
of becoming a feature; "wouldn't it be nice" requests do not.
19+
- For anything beyond a small fix, **open an issue with the use case
20+
first**. A 200-line PR that gets closed is more friction than a
21+
five-line issue that gets a "yes, send it" reply. This is the
22+
gate-before-feature stance the project runs on.
23+
24+
## License + forking
25+
26+
- MIT license, no Contributor License Agreement.
27+
- Forking is fine and explicitly OK — if a feature is out of scope
28+
here, your fork is the right home. The project's
29+
[§"What we will not do"][wnwd] section is honest about hard limits
30+
(no gateway features, no SDK instrumentation, no semantic
31+
interpretation of captured content, no credential-value matching);
32+
if you need any of those, a fork or a downstream tool is the
33+
expected path, not a PR against this repo.
34+
35+
## Code of conduct
36+
37+
Contributors are expected to follow the project's
38+
[CODE_OF_CONDUCT.md](../CODE_OF_CONDUCT.md) (Contributor Covenant
39+
v2.1). Report issues by opening a GitHub issue and mentioning the
40+
maintainer.
41+
42+
## Security
43+
44+
Security issues should follow the process in [SECURITY.md](../SECURITY.md).
45+
Do not file public issues for vulnerabilities.
46+
47+
[wnwd]: ../ROADMAP.md#what-we-will-not-do
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
---
2+
name: Bug report
3+
about: Capture path, read API, viewer, or plugin behaving incorrectly.
4+
title: ""
5+
labels: bug
6+
assignees: ""
7+
---
8+
9+
<!--
10+
Before filing: search existing issues. Best-effort maintenance, one
11+
contributor, no SLA. A report with the fields below filled in moves
12+
much faster than a report without them.
13+
14+
Redact bearer tokens / API keys before pasting JSONL or logs. The
15+
capture path stores them unredacted on disk (this is documented; see
16+
SECURITY.md) but they do not belong in a public issue.
17+
-->
18+
19+
## Version
20+
21+
```
22+
$ api-log -version
23+
# paste output
24+
```
25+
26+
If running from `main`, paste the commit SHA (`git rev-parse HEAD`).
27+
28+
## Deployment shape
29+
30+
- Install method: Docker Compose / native binary / `go install` / built from source
31+
- OS + arch: e.g. `linux/amd64`, `darwin/arm64`
32+
- Upstream gateway in front of which api-log is deployed (sub2api / CPA / new-api / other / none)
33+
- Reverse proxy in front of api-log, if any (Caddy / nginx / none)
34+
35+
## Steps to reproduce
36+
37+
1. ...
38+
2. ...
39+
3. ...
40+
41+
**Expected:** what should have happened.
42+
43+
**Actual:** what did happen.
44+
45+
If the bug involves a specific HTTP request, paste the request shape
46+
(method, path, relevant headers with credentials redacted, body
47+
shape — not the literal body if it carries customer data).
48+
49+
## `/healthz` output
50+
51+
The counters and storage blocks are the maintainer's primary
52+
diagnostic anchor. Capture them at the time of the incident if you
53+
still can:
54+
55+
```bash
56+
curl -s http://localhost:7862/healthz | jq '{counters, storage}'
57+
```
58+
59+
```json
60+
# paste output here
61+
```
62+
63+
## Sample JSONL line (if capture-related)
64+
65+
If the bug is about what got recorded (missing fields, wrong shape,
66+
truncation, parse failure), paste one JSONL line that reproduces it.
67+
Redact `Authorization` / `x-api-key` / equivalent header values
68+
yourself before pasting.
69+
70+
```json
71+
# paste here
72+
```
73+
74+
## Logs around the incident
75+
76+
stderr from the api-log process (or `docker logs` / `journalctl -u
77+
api-log`) covering ~30 seconds before and after the incident.
78+
79+
```
80+
# paste here
81+
```
82+
83+
## Anything else
84+
85+
Plugin config in effect (`config.yaml` plugins block + any
86+
`PUT /api/config/plugins` overrides), retention settings, anything
87+
non-default that might be relevant.

‎.github/ISSUE_TEMPLATE/config.yml‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: Security report
4+
url: https://github.com/2nd1st/api-log/security/advisories/new
5+
about: Do not file a public issue. Open a private security advisory.
6+
- name: Contributing guide
7+
url: https://github.com/2nd1st/api-log/blob/main/CONTRIBUTING.md
8+
about: Scope, gate-before-feature stance, and the pre-PR command set live here.
9+
- name: Read the docs first
10+
url: https://github.com/2nd1st/api-log#readme
11+
about: README, ARCHITECTURE.md, ROADMAP.md, and SECURITY.md cover most questions before they need to be asked.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
name: Feature request
3+
about: Propose a change to the core proxy, read API, or shipped plugins.
4+
title: ""
5+
labels: enhancement
6+
assignees: ""
7+
---
8+
9+
<!--
10+
api-log is deliberately small. The "What we will not do" section of
11+
ROADMAP.md lists the categories of work that will be closed on sight:
12+
no gateway features (auth / routing / retries / rate limiting / caching
13+
/ rewriting), no SDK instrumentation, no semantic interpretation of
14+
recorded content, no automatic redaction in the capture path, no
15+
matching on credential-carrying header values.
16+
17+
The default answer for new behavior is "off-by-default plugin", not
18+
"core change". If you have not read ROADMAP.md, do that first.
19+
20+
Requests phrased as "wouldn't it be nice if api-log could..." will be
21+
closed. Requests grounded in an adopter use case the maintainer can
22+
reason about will be considered.
23+
-->
24+
25+
## Adopter use case
26+
27+
Concrete situation in your own deployment that this would address.
28+
Which gateway, what kind of traffic, what you are trying to learn or
29+
do that you cannot do today. Numbers help (trace volume, request
30+
shape, time horizon).
31+
32+
## Why this cannot be a plugin
33+
34+
api-log ships a plugin surface (`text-replace`, `text-append`,
35+
`path-filter`, `capture-filter`) and the surface is intentionally
36+
extensible. Before proposing a core change, explain why an
37+
off-by-default plugin — yours, in a fork or sidecar repo — cannot
38+
deliver the same outcome.
39+
40+
## Existing surface that comes close
41+
42+
What in api-log today (read API endpoint, JSONL field, plugin, env
43+
knob) gets partway to your use case? What is the gap?
44+
45+
Link the relevant section of ARCHITECTURE.md or README.md.
46+
47+
## Acceptable scope
48+
49+
To bound review, name what is **in** scope and what is explicitly
50+
**out** of scope for the proposed change.
51+
52+
- **In scope:** ...
53+
- **Out of scope:** ...
54+
55+
A request that does not bound itself tends to grow during
56+
discussion. Bound it up front.
57+
58+
## Alternatives considered
59+
60+
Other ways you considered solving this (downstream tooling over the
61+
JSONL, a sidecar over `data/`, a change to the upstream gateway
62+
instead, etc.) and why the proposal here is the one you landed on.

‎.github/PULL_REQUEST_TEMPLATE.md‎

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<!--
2+
api-log is best-effort, one contributor, no SLA. PRs that fill in the
3+
boxes below land faster than PRs that do not.
4+
5+
If this PR changes the JSONL line shape, the on-disk layout, or the
6+
HTTP read API contract: read PHILOSOPHY.md § principle 6 first.
7+
Wire-format contracts follow append-only / new-format-key migration
8+
discipline; field renames and removals do not land.
9+
10+
If this PR adds capture-path behavior, plugin scope, or anything
11+
that touches what gets recorded: read ROADMAP.md § "What we will
12+
not do" first.
13+
-->
14+
15+
## What changed + why
16+
17+
One paragraph. The "why" matters more than a file-by-file recap of
18+
the "what" — the diff already shows the what.
19+
20+
## Trade-off chosen
21+
22+
Name the alternative you considered and rejected, and the reason.
23+
"Did the obvious thing" is acceptable for small changes; for
24+
anything touching the capture path, read API, plugin surface, or
25+
on-disk format, name the alternative explicitly.
26+
27+
## Tests
28+
29+
- [ ] Added unit / integration tests covering the change.
30+
- [ ] No tests added — reason: <!-- e.g. docs-only, mechanical refactor with existing coverage -->
31+
32+
## Local checks
33+
34+
- [ ] `go test -race ./...` clean.
35+
- [ ] `golangci-lint run` clean (v2 config).
36+
- [ ] Integration harness `./tests/integration/run.sh` clean (if the change touches the proxy / read API / plugin path).
37+
38+
## CHANGELOG
39+
40+
- [ ] Added an entry under `## [Unreleased]` in `CHANGELOG.md`.
41+
- [ ] No CHANGELOG entry — reason: <!-- e.g. internal-only refactor, test-only change, docs typo -->
42+
43+
If yes, paste the entry you added:
44+
45+
```
46+
### Added / Changed / Fixed / Removed
47+
- ...
48+
```
49+
50+
## Docs
51+
52+
- [ ] `README.md` / `README.zh.md` touched if user-visible surface changed.
53+
- [ ] `ARCHITECTURE.md` touched if on-disk format, read API contract, or write path changed.
54+
- [ ] `ROADMAP.md` touched if this lands a tracked item or moves the "deferred" list.
55+
- [ ] `SECURITY.md` touched if the threat model or operator responsibilities changed.
56+
- [ ] No docs change needed.
57+
58+
## Linked issue
59+
60+
Closes #<!-- number --> <!-- or "n/a" with a one-line reason -->

‎ARCHITECTURE.md‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,3 +1205,70 @@ buffer-then-expose machinery only when at least one registered plugin
12051205
opts in via the new interface. Re-open Phase D when a real adopter
12061206
files an issue with a concrete use case that BEFORE-tools-array,
12071207
`ActionIntercept`, or Observer-scrub genuinely cannot serve.
1208+
1209+
---
1210+
1211+
## 14. What this is not
1212+
1213+
The shape of the project is as much defined by what it refuses to
1214+
do as by what it does. The points below are architectural, not
1215+
roadmap items — they will not change without a §1-level
1216+
amendment.
1217+
1218+
### 14.1 Single-node only
1219+
1220+
One binary, one `<data_dir>`. There is no clustering layer, no
1221+
shared-storage replication, no leader election, no cross-node
1222+
trace ID coordination. Two binaries pointed at the same data
1223+
directory will collide at the ULID-generation and SQLite-writer
1224+
layers; see [docs/operations.md](./docs/operations.md)
1225+
"Multi-instance" for the failure modes.
1226+
1227+
Horizontal capture scale is solved by running independent
1228+
instances — one per LLM gateway upstream, each with its own data
1229+
directory — and aggregating downstream from the JSONL trees. The
1230+
project is shaped for the "tcpdump in front of one gateway"
1231+
deployment; a multi-tenant control plane is out of scope.
1232+
1233+
### 14.2 JSONL is truth; SQLite is rebuildable cache
1234+
1235+
§1 states the invariant; this section restates it as a posture.
1236+
Adopters can delete `index.sqlite` at any time and the binary will
1237+
rebuild it from the JSONL tree on next startup. Backup strategies
1238+
treat the JSONL tree as the only artifact that matters; the SQLite
1239+
index is a query-acceleration convenience, not a second source of
1240+
record.
1241+
1242+
The forward-referenced `api-log rebuild` subcommand (ROADMAP
1243+
"Day-2 operations") will surface this as an explicit operator
1244+
command rather than the implicit startup-on-empty-data-dir
1245+
behavior, but the underlying invariant is unchanged.
1246+
1247+
### 14.3 WAL means concurrent readers, single writer
1248+
1249+
The SQLite WAL mode documented in §4 buys us many concurrent
1250+
readers (the read API, plus any external `sqlite3` session a human
1251+
or a tool opens against the file) coexisting with the
1252+
writer goroutine. It does **not** buy us multiple writers. The
1253+
write path is one goroutine, full stop; the channel in front of it
1254+
absorbs bursts and drops with a counter when it saturates (§7.3).
1255+
Adopters writing custom tooling against `index.sqlite` should open
1256+
read-only connections.
1257+
1258+
### 14.4 No gateway behavior in the capture path
1259+
1260+
A consolidated restatement of the ROADMAP "What we will not do"
1261+
list as it intersects this document: the proxy does not
1262+
authenticate, route, retry, rate-limit, cache, rewrite, or
1263+
redact in the capture path. The `req.headers` and `resp.headers`
1264+
captured in the JSONL line are what the proxy actually forwarded
1265+
(modulo the §10.4 `X-Forwarded-*` suppression and the standard
1266+
hop-by-hop strip ReverseProxy already performs). Plugins
1267+
(§6.7 / ROADMAP §11) are the only sanctioned mechanism for
1268+
operator-side mutation, and they are off by default.
1269+
1270+
---
1271+
1272+
Operator-facing material — backup procedure, manual WAL checkpoint
1273+
one-liner, retention cross-reference, multi-instance behavior — is
1274+
not in this document. See [docs/operations.md](./docs/operations.md).

0 commit comments

Comments
 (0)