Skip to content

docs(api): inventory and document non-conflicting TypeScript API - #86

Draft
seonghobae wants to merge 20 commits into
mainfrom
docs/rate-limit-public-api
Draft

docs(api): inventory and document non-conflicting TypeScript API#86
seonghobae wants to merge 20 commits into
mainfrom
docs/rate-limit-public-api

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Purpose

Advance #82 with a deterministic repository-wide TypeScript public-export inventory and beginner-readable documentation for Noema's owned credential-boundary modules. This remains a documentation-quality slice, not the owner of replay-ordering or canonical repository architecture.

Fresh source identity

  • PR base: main.
  • Protected main: c85d710804139c0697d7ef8fa47d02b1389e6d84 (fix(security): update transitive nanoid for CVE-2026-67213 #76 integrated; the historical nanoid prerequisite is complete).
  • Head branch: docs/rate-limit-public-api.
  • Exact current head: 1d8b9a3fafc07f0df6e79a286f141d21e22bc1f9.
  • Fresh compare against protected main: diverged, 20 commits ahead / 1 behind, merge base 9adb784902cae19a150146a8fadd6a0491f67814.
  • The branch remains Draft. Its historical audit failure does not describe current protected main, but no predecessor evidence transfers after refresh.

Implemented documentation boundary

test/rate-limit-public-api-docs.test.ts uses the TypeScript compiler/program/type-checker without executing production modules. It resolves direct, named, star and namespace exports to their actual source symbols, preventing an unrelated same-name documented declaration from creating a false PASS. It requires meaningful adjacent JSDoc and callable parameter/return documentation under the deterministic inventory.

test/public-api-diagnostic-bounds.test.ts also keeps diagnostic prose aligned with actual constructors rather than calling an unbounded message bounded.

The stale head documents public boundaries in src/rate-limit.ts, src/entrypoint.ts, src/runtime-entrypoint.ts, src/outbound-fetch-policy.ts, src/oidc-replay.ts, src/index.ts, and src/worker.ts.

Historical exact-head evidence

For 1d8b9a3fafc07f0df6e79a286f141d21e22bc1f9 on the old base snapshot:

  • application CI 31345138899 passed typecheck and 63 test files / 653 tests with configured owned statements/branches/functions/lines at 100%, then failed at the then-inherited nanoid audit;
  • reviewer-ci 31345138909: terminal success;
  • central Security Scan 31345138893: terminal success.

#76 now makes the old audit failure historical, but the stale head/checks do not become current protected-base evidence.

Review ownership

No model/comment/check/status evidence is a qualifying formal approval.

Current dependency / refresh rule

  1. Converge/integrate canonical fix(security): bind workflow source and document MSA boundaries #71 onto protected main without losing current successor/protected truth.
  2. Rebuild/integrate only fix(security): claim verified OIDC replay before token mint #83's replay-before-token-mint repair onto the resulting protected lineage and prove it operationally.
  3. From that stable protected source, rebuild only docs(api): inventory and document non-conflicting TypeScript API #86's unique public-API documentation/inventory delta rather than carrying stale source copies forward.
  4. Re-run the deterministic public-export inventory against the actual then-current source and update JSDoc for any exports added/changed since this stale snapshot.
  5. Require fresh exact-head application CI, reviewer-ci, eligible protected-base Security Scan and current review evidence.
  6. Reconcile canonical docs/TEST_STRATEGY.md, documentation fitness/traceability, CLAUDE.md and CHANGELOG on the integrated lineage without creating a parallel fix(security): bind workflow source and document MSA boundaries #71 architecture authority.
  7. After protected merge, run the export inventory on protected main and retain proof that a newly undocumented public export fails closed.

No runtime behavior change, protection weakening, synthetic approval, repair workflow, version bump, release or deployment authority is introduced.

Related: #27, #29, #71, #76, #81, #82, #83, #84

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

TypeScript 공개 API와 Worker 진입점에 JSDoc 설명을 추가했습니다. OIDC replay, outbound fetch, rate-limit의 계약과 실패 처리를 문서화했습니다. 공개 export의 JSDoc과 필수 용어를 검증하는 테스트를 추가했습니다.

Changes

공개 API 문서화

Layer / File(s) Summary
런타임 및 요청 경계 문서화
src/entrypoint.ts, src/index.ts, src/runtime-entrypoint.ts, src/worker.ts
Worker 런타임, readiness 라우팅, 교환 요청, OIDC 입력, JSON 본문 제한 및 실패 응답의 동작을 문서화했습니다.
Outbound fetch 정책 문서화
src/outbound-fetch-policy.ts
credential egress 검증, HTTPS allowlist, redirect, 응답 크기, timeout 및 전역 정책 설치·복원 동작을 문서화했습니다.
OIDC replay 보호 문서화
src/oidc-replay.ts
replay 환경, claim 결정, 오류, Durable Object 이름 생성, 원자적 처리 및 alarm 정리를 문서화했습니다.
Rate-limit 문서화와 공개 API 검증
src/rate-limit.ts, test/rate-limit-public-api-docs.test.ts
분산 rate-limit 동작을 문서화했습니다. 공개 export의 인접 JSDoc, @param, @returns, re-export 연결 및 필수 용어를 검사합니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

  • ContextualWisdomLab/noema 이슈 82: TypeScript 공개 API JSDoc과 결정적 문서 커버리지 테스트를 추가하는 변경과 직접 연결됩니다.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 TypeScript 공개 API 인벤토리 작성과 문서화라는 변경의 주요 목적을 정확하고 간결하게 설명합니다.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/rate-limit-public-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae seonghobae changed the title docs(api): document rate-limit public TypeScript API docs(api): inventory and document non-conflicting TypeScript API Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review the unchanged exact head bab102f57293ef4f81a94016ce705ec9df7ab3c4. Focus on whether the TypeScript AST inventory actually covers every intended public export/re-export shape without executing production code, whether JSDoc adjacency/inheritance can false-pass, and whether the added documentation accurately describes credential/trust/failure boundaries. This review is diagnostic evidence only and does not substitute for qualifying independent merge approval.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== checked-out revision =='
git rev-parse HEAD
git status --short

echo '== PR diff summary =='
git diff --stat 9adb784902cae19a150146a8fadd6a0491f67814 HEAD
git diff --name-only 9adb784902cae19a150146a8fadd6a0491f67814 HEAD

echo '== candidate file outlines =='
for f in \
  test/rate-limit-public-api-docs.test.ts \
  src/rate-limit.ts \
  src/entrypoint.ts \
  src/runtime-entrypoint.ts \
  src/outbound-fetch-policy.ts \
  src/oidc-replay.ts \
  src/index.ts \
  src/worker.ts
do
  if [ -f "$f" ]; then
    echo "--- $f"
    ast-grep outline "$f" --items all || true
  fi
done

echo '== all TypeScript export declarations in src =='
ast-grep run \
  --lang typescript \
  --pattern 'export $$$' \
  src || true

echo '== explicit re-export declarations in src =='
rg -n -C2 --glob '*.ts' \
  '^\s*export\s*(\*|\{.*\})\s*(from\s*["'\''])|^\s*export\s*\{.*\}\s*from\s*["'\'']' \
  src || true

Length of output: 15436


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== inventory test: discovery, JSDoc, and export collection =='
sed -n '1,230p' test/rate-limit-public-api-docs.test.ts

echo '== inventory test: assertions and documentation contract =='
sed -n '231,360p' test/rate-limit-public-api-docs.test.ts

echo '== changed content =='
git diff --unified=80 9adb784902cae19a150146a8fadd6a0491f67814 HEAD -- \
  test/rate-limit-public-api-docs.test.ts \
  src/rate-limit.ts \
  src/entrypoint.ts \
  src/runtime-entrypoint.ts \
  src/outbound-fetch-policy.ts \
  src/oidc-replay.ts \
  src/index.ts \
  src/worker.ts

echo '== source-wide export statement inventory =='
rg -n --glob '*.ts' -C2 \
  '^\s*export\s+(default\s+)?(abstract\s+)?(declare\s+)?(async\s+)?(class|function|interface|type|enum|namespace|module|const|let|var)\b|^\s*export\s*(type\s+)?\{[^}]*\}|^\s*export\s*\*' \
  src

echo '== export-assignment and CommonJS compatibility forms =='
rg -n --glob '*.ts' -C2 \
  '(^|[^[:alnum:]_])export\s*=|module\.exports|exports\.[[:alpha:]_$]' \
  src || true

echo '== all source modules collected by the test =='
fd -t f -e ts . src | sort

Length of output: 112846


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== inventory collector with line numbers =='
nl -ba test/rate-limit-public-api-docs.test.ts | sed -n '65,225p'

echo '== default Worker documentation and implementations =='
for f in src/index.ts src/worker.ts src/entrypoint.ts src/runtime-entrypoint.ts; do
  echo "--- $f"
  rg -n -C8 --glob '*.ts' '^\s*/\*\*|^\s*export\s+default\b|^\s*async\s+fetch\s*\(' "$f"
done

echo '== all named and star export forms, including multiline starts =='
rg -n -U --glob '*.ts' -C2 \
  '^\s*export\s*(type\s+)?\{[\s\S]*?^\s*\}\s*(from\s*["'\''][^"'\'']+["'\''])?\s*;|^\s*export\s+\*\s*(as\s+[A-Za-z_$][A-Za-z0-9_$]*)?\s+from\s+["'\'']' \
  src || true

echo '== TypeScript package and compiler configuration =='
fd -t f 'package.json|tsconfig.*\.json' . -d 3 -x sh -c 'echo "--- $1"; sed -n "1,220p" "$1"' sh {}

echo '== potential direct-export shapes that declarationNames does not enumerate =='
rg -n --glob '*.ts' -C2 \
  '^\s*export\s+default\s+(async\s+)?(function|class)\s*\{|^\s*export\s+(const|let|var)\s*[\{\[]|^\s*export\s+import\s+[A-Za-z_$]|^\s*export\s+as\s+namespace\b' \
  src || true

Length of output: 1514


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== inventory collector with line numbers =='
awk 'NR >= 65 && NR <= 225 { printf "%6d  %s\n", NR, $0 }' \
  test/rate-limit-public-api-docs.test.ts

echo '== default Worker documentation and implementations =='
for f in src/index.ts src/worker.ts src/entrypoint.ts src/runtime-entrypoint.ts; do
  echo "--- $f"
  rg -n -C8 '^\s*/\*\*|^\s*export\s+default\b|^\s*async\s+fetch\s*\(' "$f" || true
done

echo '== all named and star export forms =='
rg -n -U -C2 --glob '*.ts' \
  '^\s*export\s*(type\s+)?\{[\s\S]*?^\s*\}\s*(from\s*["'\''][^"'\'']+["'\''])?\s*;|^\s*export\s+\*\s*(as\s+[A-Za-z_$][A-Za-z0-9_$]*)?\s+from\s+["'\'']' \
  src || true

echo '== TypeScript package and compiler configuration =='
while IFS= read -r f; do
  echo "--- $f"
  sed -n '1,220p' "$f"
done < <(fd -t f -d 3 -E node_modules -E .git -g 'package.json' -g 'tsconfig*.json' . | sort)

echo '== direct-export shapes not enumerated by declarationNames =='
rg -n -C2 --glob '*.ts' \
  '^\s*export\s+default\s+(async\s+)?(function|class)\s*\{|^\s*export\s+(const|let|var)\s*[\{\[]|^\s*export\s+import\s+[A-Za-z_$]|^\s*export\s+as\s+namespace\b' \
  src || true

Length of output: 25546


@seonghobae I found one contract-blocking issue.

P1 — Resolve re-exports by module, and handle star re-exports
Line 129 handles ExportDeclaration, but Lines 130-140 collect only NamedExports. Therefore, export * from "./module" and export * as Namespace from "./module" are ignored. Those exports can add undocumented public API without failing this test.

The named re-export check at Lines 208-225 can also false-pass. It accepts an export when exactly one direct export has the same originalName anywhere under src. It does not resolve moduleSpecifier, local import bindings, aliases, or re-export chains. For example, export { Credential as PublicCredential } from "./a" can pass because an unrelated Credential in ./b has JSDoc.

Use TypeScript module-symbol resolution to follow each re-export to its actual declaration. If resolution is unavailable or ambiguous, require JSDoc on the re-export itself. Process star and namespace re-exports with the same rule. This preserves static inspection and does not execute production code.

The collector otherwise parses source text without importing production modules. The direct-export adjacency check is correctly local to the declaration. The inspected credential, trust, and failure-boundary documentation matches the corresponding implementations.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/oidc-replay.ts`:
- Around line 55-65: Update the OidcReplayUnavailable constructor documentation
to remove the inaccurate “bounded” description, unless an actual message
length/content limit is intentionally added before super(message). Keep the
documented behavior aligned with the constructor’s current handling of the
message.
- Around line 130-140: Reorder the /exchange flow in worker.ts so
claimOidcTokenUsage(...) completes before baseWorker.fetch(...) can invoke
createInstallationToken(...) and issue credentials. Preserve the existing
non-2xx response handling, and ensure replayed tokens are rejected before any
credential-producing side effect occurs.

In `@src/rate-limit.ts`:
- Around line 59-61: Align the JSDoc for the fail-closed rate-limit error
constructor with its actual behavior: either enforce a bounded length before
passing message to super, or remove the “bounded” wording from the
documentation. Prefer the smallest change and update the parameter description
near the rate-limit error class/constructor.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e9c65c0b-3bba-426b-8e0e-38efef447c42

📥 Commits

Reviewing files that changed from the base of the PR and between 9adb784 and bab102f.

📒 Files selected for processing (8)
  • src/entrypoint.ts
  • src/index.ts
  • src/oidc-replay.ts
  • src/outbound-fetch-policy.ts
  • src/rate-limit.ts
  • src/runtime-entrypoint.ts
  • src/worker.ts
  • test/rate-limit-public-api-docs.test.ts

Comment thread src/oidc-replay.ts
Comment thread src/oidc-replay.ts
Comment on lines +130 to +140
/**
* Atomically claims a verified OIDC token for one-time use through the replay
* Durable Object. The response body and expiry are validated before acceptance,
* and every unavailable or contradictory result fails closed.
* @param jti Verified bounded token identifier used only to derive the opaque replay key.
* @param expiresAtEpochSeconds Verified token expiry, bounded to the accepted lifetime window.
* @param env Runtime environment containing the replay-guard Durable Object binding.
* @returns The authoritative accepted replay-claim decision.
* @throws {OidcReplayDetected} When a still-live claim already exists for this token.
* @throws {OidcReplayUnavailable} When replay protection cannot produce trustworthy evidence.
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 20 'baseWorker\.fetch|claimOidcTokenUsage' src/worker.ts || true
rg -n -C 12 'exchange|credential|installation token|issue' src --glob '*.ts' || true

Repository: ContextualWisdomLab/noema

Length of output: 50381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- src/worker.ts exchange guard section ---'
sed -n '266,398p' src/worker.ts

echo '--- src/index.ts credential exchange section ---'
sed -n '389,488p' src/index.ts

echo '--- static call-order scan ---'
python3 - <<'PY'
from pathlib import Path
paths = ["src/worker.ts", "src/index.ts"]
for path in paths:
    p = Path(path)
    lines = p.read_text().splitlines()
    print(f"\n{path}:")
    for i, line in enumerate(lines, 1):
        if "baseWorker.fetch" in line or "createInstallationToken" in line or "claimOidcTokenUsage" in line:
            print(f"{i}: {line}")
PY

Repository: ContextualWisdomLab/noema

Length of output: 9575


credential 발급 전에 replay claim을 수행하세요.

src/worker.ts /exchange 경로는 response.status < 200 || response.status >= 300일 때만 먼저 리턴하고, 성공 응답을 받은 뒤 claimOidcTokenUsage(...)를 실행합니다. baseWorker.fetchcreateInstallationToken(...)를 호출해 GitHub installation token을 반환하면, 재사용된 OIDC token도 credential 응답을 먼저 받은 뒤 401로 처리됩니다. baseWorker.fetch(...) 호출을 replay claim 이후로 옮기거나, credential 발급을 단일 side-effect 이후로 반환되도록 순서도 변경하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/oidc-replay.ts` around lines 130 - 140, Reorder the /exchange flow in
worker.ts so claimOidcTokenUsage(...) completes before baseWorker.fetch(...) can
invoke createInstallationToken(...) and issue credentials. Preserve the existing
non-2xx response handling, and ensure replayed tokens are rejected before any
credential-producing side effect occurs.

Comment thread src/rate-limit.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant