You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Implement Phase 126-127: public repo sharing (visibility, attach-as-reader, first-index gate, refresh throttle)
Adds repos.visibility/owner_user_id and repo_grants.source columns, a
gitsema repos visibility CLI command, and registration-flow logic in
POST /api/v1/remote/index for auto-granting read access on public repos,
gated by auth.allowPublicAutoIndex and throttled by
auth.minReindexIntervalSeconds. Fixes a registry-DB/active-DB FK mismatch
discovered during testing: registry.db (clone/index-path bookkeeping) and
the active session DB (auth/grants) are independent SQLite files with
separate FK-enforced users tables, so ownerUserId is now mirrored only into
the active DB rather than written to both.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYNogpqPb8oyTF3B5Ebu5p
* refactor: simplify public-repo-sharing throttle/grant logic and test fixtures
Hoist the duplicated non-owner-on-public-repo guard into a single named
boolean, add TTL cleanup for the reindex throttle map (matching the
existing jobs map pattern), and extract repeated test fixture setup into
a shared helper.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYNogpqPb8oyTF3B5Ebu5p
* docs: require simplify passes to log deferred findings in feature-ideas.md
Adds a CLAUDE.md rule so skipped /simplify findings aren't lost to chat
history, and backfills the two deferred findings from the Phase 126/127
public-repo-sharing simplify pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYNogpqPb8oyTF3B5Ebu5p
* docs: note send_later/CI-webhook gaps for PR babysitting in this environment
Records that this environment lacks send_later and that CI success
doesn't trigger a webhook, so PR-watching sessions need a manual
~7-minute poll loop instead.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYNogpqPb8oyTF3B5Ebu5p
---------
Co-authored-by: Claude <noreply@anthropic.com>
Add public repo sharing: persisted repos can now be flagged `public` (`gitsema repos visibility <repo-id> public|private`), auto-granting `read` access to non-owner callers who index an existing public repo, gated by a first-index allow-list (`auth.allowPublicAutoIndex`/`GITSEMA_PUBLIC_AUTO_INDEX`) and a per-user re-index throttle (`auth.minReindexIntervalSeconds`/`GITSEMA_MIN_REINDEX_INTERVAL_SECONDS`).
Copy file name to clipboardExpand all lines: CLAUDE.md
+29-2Lines changed: 29 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -27,6 +27,30 @@ When implementing a new feature or phase:
27
27
28
28
---
29
29
30
+
## Simplify passes
31
+
32
+
When running a `/simplify` pass, any finding that gets **skipped** (out of scope,
33
+
too large a refactor, judged not worth doing now) must be written up as an entry
34
+
in **`docs/feature-ideas.md`** rather than just mentioned in the chat summary —
35
+
otherwise the finding is lost once the session ends.
36
+
37
+
---
38
+
39
+
## PR babysitting in this environment
40
+
41
+
The `send_later` tool (claude-code-remote MCP server) is **not available** in
42
+
this environment. CI turning green also does **not** trigger a webhook event —
43
+
only CI failures, new review comments, and similar activity do. This means a
44
+
subscribed PR can sit at "CI passed" indefinitely with no event to notice it.
45
+
46
+
When babysitting/watching a PR here, compensate by running a short polling
47
+
wait (e.g. a backgrounded `sleep ~7m` via Bash `run_in_background`, repeated as
48
+
needed) and re-checking CI status (`pull_request_read` → `get_status` /
49
+
`get_check_runs`) after each wait, instead of relying on `send_later` or
50
+
webhook delivery alone.
51
+
52
+
---
53
+
30
54
## Releases & changesets
31
55
32
56
This repo uses [changesets](https://github.com/changesets/changesets) for versioning, `CHANGELOG.md` generation, and npm publishing (OIDC trusted publishing — no npm token).
@@ -460,7 +484,7 @@ gitsema index
460
484
461
485
**Pluggable storage backends (Phase 101–103):** all reads/writes go through async `MetadataStore` / `VectorStore` / `FtsStore` interfaces (`src/core/storage/types.ts`). The default `sqlite` backend wraps the schema below; `postgres` routes metadata + FTS through Postgres (pgvector for vectors), and `qdrant` uses Qdrant for vectors with Postgres for metadata/FTS. Select via `storage.*` config or `GITSEMA_STORAGE_*` env vars (see Configuration), inspect with `gitsema storage info`, and copy between backends with `gitsema storage migrate`.
462
486
463
-
**Schema overview (current schema v30):**
487
+
**Schema overview (current schema v31):**
464
488
465
489
| Table | Purpose |
466
490
|---|---|
@@ -496,6 +520,8 @@ gitsema index
496
520
|`repo_grants`| Per-user repo access grants (`read`/`write`/`owner`, optional branch-glob pattern); replaces the binary `repo_tokens` model for new deployments; added in v28 (Phase 123, multi-tenant-auth §5 Phase B) |
497
521
|`sso_identities`| Linked external OIDC/SSO identities (`provider` + `external_id` → `user_id`, unique per identity); added in v29 (Phase 124, multi-tenant-auth §5 Phase C) |
498
522
|`audit_log`| Identity/authorization audit trail — grant create/revoke, token create/revoke, login success/failure, org membership changes, repo org moves; no FK constraints (historical record outlives referenced rows); added in v30 (Phase 125, multi-tenant-auth §5 Phase D) |
523
+
|`repos.visibility` / `repos.owner_user_id`| Repo visibility flag (`private`/`public`) and first-claimer owner; added in v31 (Phase 126, public-repo-sharing) |
524
+
|`repo_grants.source`| Provenance of an auto-issued grant, e.g. `auto-public` for attach-as-reader grants; added in v31 (Phase 126, public-repo-sharing) |
499
525
500
526
**FTS5 note:** Blobs indexed before Phase 11 have no FTS5 content. `--hybrid` search only applies to blobs with FTS5 entries. `--include-content` in evolution dumps also depends on FTS5 content. Use `gitsema backfill-fts` to populate FTS5 content for older index entries.
501
527
@@ -519,7 +545,8 @@ gitsema index
519
545
- v27 → v28: Added `orgs`, `org_members`, `repo_grants` tables (+ indexes) and a `repos.org_id` column for org/grant authorization (Phase 123 / multi-tenant-auth §5 Phase B)
- v30 → v31: Added `visibility` and `owner_user_id` columns (+ index) to `repos`, and a `source` column to `repo_grants`, for public repo sharing (Phase 126 / public-repo-sharing)
549
+
-**Current version: 31**
523
550
524
551
Schema changes require updating both `src/core/db/schema.ts` and the migration logic in `src/core/db/sqlite.ts`.
Copy file name to clipboardExpand all lines: README.md
+12Lines changed: 12 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -124,6 +124,7 @@ All commands support a top-level `--verbose` flag (or `GITSEMA_VERBOSE=1`) for d
124
124
|`gitsema repos grants <repo-id>`| List grants on a repo (operator-only) |
125
125
|`gitsema repos revoke <repo-id> <username>`| Revoke a user's grants on a repo (operator-only) |
126
126
|`gitsema repos move-to-org <repo-id> <org>`| Move a repo to a different org; grants survive untouched (operator-only) |
127
+
|`gitsema repos visibility <repo-id> public\|private`| Set a persisted repo's visibility flag, gating attach-as-reader auto-grants (operator-only) |
127
128
|`gitsema auth sso link <provider> <external-id> <username>`| Link an external SSO/OIDC identity to an existing user; provider must be in `GITSEMA_SSO_PROVIDERS` (operator-only) |
Copy file name to clipboardExpand all lines: docs/PLAN.md
+44-1Lines changed: 44 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4862,10 +4862,53 @@ that deprecated it, and its removal status.
4862
4862
|**126**| §5 Phase 1 | Visibility flag + attach-as-reader |`repos.visibility` (`'private'\|'public'`, default `'private'`) + `ownerUserId` columns; `gitsema repos visibility <repoId> public\|private` CLI (owner/superadmin only); registration-flow change in `src/server/routes/remote.ts` auto-issuing a `repo_grants` reader row when a second user attaches to an existing public repo's shared index. |
4863
4863
|**127**| §5 Phase 2 | First-index gate + refresh throttle |`auth.allowPublicAutoIndex`/`GITSEMA_PUBLIC_AUTO_INDEX` config gate (default `false`) restricting who may register a brand-new public-flagged repo; `auth.minReindexIntervalSeconds` per-`(user, repoId)` refresh throttle returning `429`/`Retry-After`. No hard dependency on Phase 126 beyond the `visibility` column existing. |
4864
4864
4865
-
**Status:** not started — draft design, scheduled here per `/phase-plan`.
4865
+
**Status:** ✅ complete *(completed vNEXT)*. Implemented in
Copy file name to clipboardExpand all lines: docs/feature-ideas.md
+46-1Lines changed: 46 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
This document tracks upcoming feature ideas that are **not yet in active development** (not in `PLAN.md`) and haven't been **fully designed** (no design file). It's a staging area for "what now?" questions and medium-term product direction.
4
4
5
-
**Last updated:** 2026-06-23 (added audit log coverage enforcement idea, found during the Phase 125 `/simplify` review; refined public-repo sharing's access-control half into `docs/public-repo-sharing-plan.md` and the superadmin-locked model set idea into `docs/locked-model-set-plan.md`; kept cross-repo blob dedup as an open idea)
5
+
**Last updated:** 2026-06-23 (added the public-repo-sharing throttle/policy-extraction idea, found during the Phase 126/127 `/simplify` review; added audit log coverage enforcement idea, found during the Phase 125 `/simplify` review; refined public-repo sharing's access-control half into `docs/public-repo-sharing-plan.md` and the superadmin-locked model set idea into `docs/locked-model-set-plan.md`; kept cross-repo blob dedup as an open idea)
6
6
**Audience:** Developers considering next phases; product planning
7
7
8
8
> **Note:** As of this update, the LSP/MCP remote-delegation foundation this
@@ -473,6 +473,51 @@ shapes (none chosen yet):
473
473
474
474
---
475
475
476
+
## Public Repo Sharing: Throttle/Rate-Limit Unification & Policy Extraction
477
+
478
+
### Problem
479
+
- Found during the `/simplify` review of Phase 126/127 (public-repo-sharing).
480
+
`checkAndRecordReindexThrottle()` (`src/server/routes/remote.ts`) is a
481
+
bespoke per-`(repoId, userId)` cooldown map, separate from the generic
482
+
abuse-prevention rate limiter in `src/server/middleware/rateLimiter.ts`
483
+
(`express-rate-limit`, keyed by Bearer token/IP, fixed window). They serve
484
+
different concerns today — one is a global RPM cap, the other a
485
+
business-rule re-index cooldown — but having two independent
486
+
rate-limiting mechanisms in the same route module is worth revisiting if
487
+
a third throttle-shaped requirement shows up.
488
+
- The same review flagged that the 2c/2d/2e public-repo gate/throttle/grant
489
+
logic in the `POST /api/v1/remote/index` handler (first-index gate,
490
+
refresh throttle, attach-as-reader auto-grant) could be extracted into a
491
+
single `applyPublicRepoPolicy()` function for readability, but that was
492
+
judged too large a restructuring for a cleanup pass on already-shipped
493
+
code.
494
+
495
+
### Intended Behavior
496
+
No design committed yet. Two independent, optional follow-ups:
497
+
- If a third per-key throttle need appears, consider whether a shared
498
+
generic "keyed cooldown" utility (used by both `rateLimiter.ts` and
499
+
`checkAndRecordReindexThrottle`) is worth building, vs. keeping them
500
+
separate as distinct concerns.
501
+
- Extract the public-repo gate/throttle/grant sequence in
502
+
`src/server/routes/remote.ts` into a named `applyPublicRepoPolicy()` (or
503
+
similar) function once it grows another condition or gets touched again,
504
+
rather than as a standalone refactor now.
505
+
506
+
### Design Gaps
507
+
-[ ] Whether a generic keyed-cooldown abstraction is worth the indirection
508
+
given only one current caller (`checkAndRecordReindexThrottle`).
509
+
-[ ] Where the line is for "policy extraction" — at what point does the
510
+
2c/2d/2e sequence justify its own function vs. staying inline.
511
+
512
+
### Effort Estimate
513
+
- Small either way — both are isolated, mechanical refactors with existing
514
+
test coverage to verify against.
515
+
516
+
### Prerequisites
517
+
- None — both are optional cleanups on already-shipped Phase 126/127 code.
518
+
519
+
---
520
+
476
521
## Related Issues & Documents
477
522
478
523
-**Parity tracking:** See `docs/parity.md` for tool availability across interfaces
0 commit comments