docs(git-sync): document GIT_SYNC_BACKEND_TIMEOUT_MS, drop dead consts, fix dangling plan refs

Address the non-red-team documentation/cleanup items from review #1679:
- Document the GIT_SYNC_BACKEND_TIMEOUT_MS watchdog (git http-backend) in
  .env.example and add it to the environment validation schema — it was used
  (getGitSyncBackendTimeoutMs, default 120000) but undocumented/unvalidated.
- Remove the dead GIT_SYNC_DEBOUNCE_MS_DEFAULT / GIT_SYNC_POLL_INTERVAL_MS_DEFAULT
  exports (never imported; environment.service is the single source of defaults).
- Redirect the dangling `plan §X.Y` comment references to issue #194 (the
  git-sync spec moved there when docs/git-sync-plan.md was deleted by this PR).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
claude code agent 227
2026-06-26 01:34:14 +03:00
parent cc835a86c0
commit e9c93fba5e
8 changed files with 22 additions and 16 deletions

View File

@@ -238,6 +238,11 @@ MCP_DOCMOST_PASSWORD=
# (default: 2000).
# GIT_SYNC_DEBOUNCE_MS=2000
#
# Watchdog timeout in ms for the spawned `git http-backend` process serving a
# git smart-HTTP push (default: 120000). A stalled/hung receive-pack is killed
# after this deadline so it cannot hold the per-space lock forever.
# GIT_SYNC_BACKEND_TIMEOUT_MS=120000
#
# Defense-in-depth absolute cap on soft-deletes applied per push cycle
# (default: 5). A non-convergent / phantom-absence cycle can never trash more
# than this many pages without an explicit override.

View File

@@ -16,7 +16,7 @@
* editor-ext ProseMirror documents must survive a full round trip through the
* actual server write path without losing any node / mark / attribute.
*
* Pipeline per document (plan §13.1):
* Pipeline per document (issue #194 §13.1):
* 1. md = convertProseMirrorToMarkdown(content) // git-sync export
* 2. doc = await markdownToProseMirror(md) // git-sync import
* 3. push `doc` through the REAL editor-ext Yjs write path the server uses:
@@ -26,12 +26,12 @@
* (apps/server/src/collaboration/extensions/persistence.extension.ts:96/115)
* with the same `tiptapExtensions` (collaboration.util.ts) and the same
* `@hocuspocus/transformer`, so the gate exercises the real schema
* validation that runs on a git-sync write (plan §3.3).
* validation that runs on a git-sync write (issue #194 §3.3).
* 4. assert docsCanonicallyEqual(canon(original), canon(normalized)) === true
*
* Any node / mark / attr that editor-ext drops (because the git-sync
* docmost-schema named it differently, or declares a different default) makes
* the gate FAIL for that document — exactly the schema-divergence plan §3.3 /
* the gate FAIL for that document — exactly the schema-divergence issue #194 §3.3 /
* §13.1 warn about. Genuine, irreducible divergences are isolated into the
* clearly-named `KNOWN DIVERGENCE` block at the bottom (never silently hidden).
*

View File

@@ -10,7 +10,7 @@ import { ProvenanceSource } from '../../core/auth/dto/jwt-payload';
*/
export interface AuthProvenanceData {
// ProvenanceSource includes 'git-sync' — set by the in-process git-sync data
// plane (plan §8.1) when it drives PageService writes; never from a request token.
// plane (issue #194 §8.1) when it drives PageService writes; never from a request token.
actor: ProvenanceSource;
aiChatId: string | null;
}
@@ -62,7 +62,7 @@ export function agentSourceFields<S extends string, C extends string>(
sourceKey: S,
chatKey: C,
): Partial<Record<S, ProvenanceSource> & Record<C, string | null>> {
// git-sync data-plane write (plan §8.1): stamp the source 'git-sync' with NO
// git-sync data-plane write (issue #194 §8.1): stamp the source 'git-sync' with NO
// aiChatId (it has no internal ai_chats row). Mirrors the agent branch; each
// write has a single actor, so precedence is irrelevant here.
if (provenance?.actor === 'git-sync') {

View File

@@ -4,7 +4,7 @@
* Single source of truth so a typo like 'agnet' can't slip through as a bare
* string (#143 review). Distinct from `ActorType` (auth principal kind).
*
* 'git-sync' marks writes made by the git-sync data plane (plan §8.1). It NEVER
* 'git-sync' marks writes made by the git-sync data plane (issue #194 §8.1). It NEVER
* travels in a user-facing token; it is set in-process on the collab connection
* context by the native datasource, so it cannot be spoofed from a request.
*/

View File

@@ -333,7 +333,7 @@ export class EnvironmentService {
.filter(Boolean);
}
// --- git-sync (plan §7.2) -------------------------------------------------
// --- git-sync (issue #194 §7.2) -------------------------------------------------
/** Global master switch for the git-sync control plane (default false). */
isGitSyncEnabled(): boolean {

View File

@@ -171,7 +171,7 @@ export class EnvironmentVariables {
)
CLICKHOUSE_URL: string;
// --- git-sync (plan §7.2) — all OPTIONAL. The master switch defaults off; a
// --- git-sync (issue #194 §7.2) — all OPTIONAL. The master switch defaults off; a
// required-if-enabled service user id is validated only when sync is on. ---
@IsOptional()
@@ -202,6 +202,13 @@ export class EnvironmentVariables {
@IsString()
GIT_SYNC_DEBOUNCE_MS: string;
// Watchdog timeout (ms) for the spawned `git http-backend` process (default
// 120000): a stalled receive-pack is killed so it cannot hold the per-space
// lock forever. Optional int (validated as a string env).
@IsOptional()
@IsString()
GIT_SYNC_BACKEND_TIMEOUT_MS: string;
// Defense-in-depth absolute cap on soft-deletes per push cycle (default 5): a
// non-convergent / phantom-absence cycle can never trash more than this many
// pages without an explicit override. Optional int (validated as a string env).
@@ -210,7 +217,7 @@ export class EnvironmentVariables {
GIT_SYNC_MAX_DELETES_PER_CYCLE: string;
// Required when git-sync is enabled: the service user create/move/rename/delete
// are attributed to (plan §7.2). Optional otherwise.
// are attributed to (issue #194 §7.2). Optional otherwise.
@ValidateIf((obj) => obj.GIT_SYNC_ENABLED === 'true')
@IsNotEmpty()
@IsString()

View File

@@ -39,9 +39,3 @@ export const GIT_SYNC_LOCK_PREFIX = 'git-sync:lock:';
* and the Redis lock prevents two instances racing the same space.
*/
export const GIT_SYNC_LOCK_TTL_MS = 5 * 60 * 1000;
/** Default event-debounce window (ms), overridable via GIT_SYNC_DEBOUNCE_MS. */
export const GIT_SYNC_DEBOUNCE_MS_DEFAULT = 2000;
/** Default poll-safety interval (ms), overridable via GIT_SYNC_POLL_INTERVAL_MS. */
export const GIT_SYNC_POLL_INTERVAL_MS_DEFAULT = 15000;

View File

@@ -423,7 +423,7 @@ export class GitmostDataSourceService {
actor: 'git-sync',
// PersistenceExtension reads `context.user.id` for lastUpdatedById, so the
// service user is required on the context (unlike the bare `{ actor }`
// sketch in the plan).
// sketch in issue #194).
user: { id: userId },
});
try {