overleaf-codex 0.1.0-rc.1

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.

Potentially problematic release.


This version of overleaf-codex might be problematic. Click here for more details.

Files changed (155) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +25 -0
  3. package/README.md +217 -0
  4. package/assets/olcx-mark.svg +22 -0
  5. package/dist/auth/projectAuth.d.ts +19 -0
  6. package/dist/auth/projectAuth.js +163 -0
  7. package/dist/auth/projectAuth.js.map +1 -0
  8. package/dist/auth/redact.d.ts +3 -0
  9. package/dist/auth/redact.js +7 -0
  10. package/dist/auth/redact.js.map +1 -0
  11. package/dist/auth/types.d.ts +10 -0
  12. package/dist/auth/types.js +4 -0
  13. package/dist/auth/types.js.map +1 -0
  14. package/dist/backend/index.d.ts +6 -0
  15. package/dist/backend/index.js +2 -0
  16. package/dist/backend/index.js.map +1 -0
  17. package/dist/backend/olcli/client.d.ts +329 -0
  18. package/dist/backend/olcli/client.js +1757 -0
  19. package/dist/backend/olcli/client.js.map +1 -0
  20. package/dist/backend/olcli/index.d.ts +2 -0
  21. package/dist/backend/olcli/index.js +2 -0
  22. package/dist/backend/olcli/index.js.map +1 -0
  23. package/dist/backend/overleafBackend.d.ts +41 -0
  24. package/dist/backend/overleafBackend.js +200 -0
  25. package/dist/backend/overleafBackend.js.map +1 -0
  26. package/dist/backend/types.d.ts +73 -0
  27. package/dist/backend/types.js +2 -0
  28. package/dist/backend/types.js.map +1 -0
  29. package/dist/cli-behavior.d.ts +14 -0
  30. package/dist/cli-behavior.js +59 -0
  31. package/dist/cli-behavior.js.map +1 -0
  32. package/dist/cli.d.ts +30 -0
  33. package/dist/cli.js +441 -0
  34. package/dist/cli.js.map +1 -0
  35. package/dist/commands/auth.d.ts +21 -0
  36. package/dist/commands/auth.js +104 -0
  37. package/dist/commands/auth.js.map +1 -0
  38. package/dist/commands/compile.d.ts +7 -0
  39. package/dist/commands/compile.js +73 -0
  40. package/dist/commands/compile.js.map +1 -0
  41. package/dist/commands/doctor.d.ts +11 -0
  42. package/dist/commands/doctor.js +9 -0
  43. package/dist/commands/doctor.js.map +1 -0
  44. package/dist/commands/endpoint.d.ts +23 -0
  45. package/dist/commands/endpoint.js +69 -0
  46. package/dist/commands/endpoint.js.map +1 -0
  47. package/dist/commands/init.d.ts +14 -0
  48. package/dist/commands/init.js +48 -0
  49. package/dist/commands/init.js.map +1 -0
  50. package/dist/commands/status.d.ts +4 -0
  51. package/dist/commands/status.js +5 -0
  52. package/dist/commands/status.js.map +1 -0
  53. package/dist/commands/sync.d.ts +26 -0
  54. package/dist/commands/sync.js +139 -0
  55. package/dist/commands/sync.js.map +1 -0
  56. package/dist/commands/watch.d.ts +28 -0
  57. package/dist/commands/watch.js +124 -0
  58. package/dist/commands/watch.js.map +1 -0
  59. package/dist/compile/compileFlow.d.ts +32 -0
  60. package/dist/compile/compileFlow.js +290 -0
  61. package/dist/compile/compileFlow.js.map +1 -0
  62. package/dist/compile/pdfOutput.d.ts +12 -0
  63. package/dist/compile/pdfOutput.js +64 -0
  64. package/dist/compile/pdfOutput.js.map +1 -0
  65. package/dist/config/ignoreRules.d.ts +5 -0
  66. package/dist/config/ignoreRules.js +53 -0
  67. package/dist/config/ignoreRules.js.map +1 -0
  68. package/dist/config/overleafProject.d.ts +9 -0
  69. package/dist/config/overleafProject.js +61 -0
  70. package/dist/config/overleafProject.js.map +1 -0
  71. package/dist/config/projectConfig.d.ts +6 -0
  72. package/dist/config/projectConfig.js +180 -0
  73. package/dist/config/projectConfig.js.map +1 -0
  74. package/dist/config/projectRoot.d.ts +1 -0
  75. package/dist/config/projectRoot.js +36 -0
  76. package/dist/config/projectRoot.js.map +1 -0
  77. package/dist/config/types.d.ts +50 -0
  78. package/dist/config/types.js +34 -0
  79. package/dist/config/types.js.map +1 -0
  80. package/dist/config/vscode.d.ts +10 -0
  81. package/dist/config/vscode.js +134 -0
  82. package/dist/config/vscode.js.map +1 -0
  83. package/dist/diagnostics/doctor.d.ts +8 -0
  84. package/dist/diagnostics/doctor.js +209 -0
  85. package/dist/diagnostics/doctor.js.map +1 -0
  86. package/dist/diagnostics/status.d.ts +6 -0
  87. package/dist/diagnostics/status.js +110 -0
  88. package/dist/diagnostics/status.js.map +1 -0
  89. package/dist/diagnostics/types.d.ts +33 -0
  90. package/dist/diagnostics/types.js +2 -0
  91. package/dist/diagnostics/types.js.map +1 -0
  92. package/dist/endpoint/overleafEndpoint.d.ts +36 -0
  93. package/dist/endpoint/overleafEndpoint.js +105 -0
  94. package/dist/endpoint/overleafEndpoint.js.map +1 -0
  95. package/dist/errors.d.ts +32 -0
  96. package/dist/errors.js +53 -0
  97. package/dist/errors.js.map +1 -0
  98. package/dist/sync/apply.d.ts +14 -0
  99. package/dist/sync/apply.js +92 -0
  100. package/dist/sync/apply.js.map +1 -0
  101. package/dist/sync/conflicts.d.ts +7 -0
  102. package/dist/sync/conflicts.js +59 -0
  103. package/dist/sync/conflicts.js.map +1 -0
  104. package/dist/sync/ignore.d.ts +5 -0
  105. package/dist/sync/ignore.js +74 -0
  106. package/dist/sync/ignore.js.map +1 -0
  107. package/dist/sync/plan.d.ts +3 -0
  108. package/dist/sync/plan.js +197 -0
  109. package/dist/sync/plan.js.map +1 -0
  110. package/dist/sync/snapshot.d.ts +13 -0
  111. package/dist/sync/snapshot.js +82 -0
  112. package/dist/sync/snapshot.js.map +1 -0
  113. package/dist/sync/state.d.ts +16 -0
  114. package/dist/sync/state.js +214 -0
  115. package/dist/sync/state.js.map +1 -0
  116. package/dist/sync/types.d.ts +113 -0
  117. package/dist/sync/types.js +4 -0
  118. package/dist/sync/types.js.map +1 -0
  119. package/dist/testing/fakeBackend.d.ts +27 -0
  120. package/dist/testing/fakeBackend.js +213 -0
  121. package/dist/testing/fakeBackend.js.map +1 -0
  122. package/dist/watch/queue.d.ts +2 -0
  123. package/dist/watch/queue.js +91 -0
  124. package/dist/watch/queue.js.map +1 -0
  125. package/dist/watch/types.d.ts +52 -0
  126. package/dist/watch/types.js +2 -0
  127. package/dist/watch/types.js.map +1 -0
  128. package/dist/watch/watcher.d.ts +6 -0
  129. package/dist/watch/watcher.js +58 -0
  130. package/dist/watch/watcher.js.map +1 -0
  131. package/dist/watch/workflow.d.ts +30 -0
  132. package/dist/watch/workflow.js +62 -0
  133. package/dist/watch/workflow.js.map +1 -0
  134. package/docs/architecture.md +603 -0
  135. package/docs/auth.md +65 -0
  136. package/docs/cli-behavior.md +95 -0
  137. package/docs/compile.md +51 -0
  138. package/docs/design.md +82 -0
  139. package/docs/endpoint.md +84 -0
  140. package/docs/npm-packaging.md +148 -0
  141. package/docs/quickdev-queue-audit.md +193 -0
  142. package/docs/release-gates.md +119 -0
  143. package/docs/release-notes-v1.md +97 -0
  144. package/docs/security.md +61 -0
  145. package/docs/sync-state.md +305 -0
  146. package/docs/sync.md +50 -0
  147. package/docs/troubleshooting.md +124 -0
  148. package/docs/usage.md +184 -0
  149. package/examples/minimal-paper/.olcx/auth.local.example.json +7 -0
  150. package/examples/minimal-paper/.olcx/config.json +23 -0
  151. package/examples/minimal-paper/README.md +88 -0
  152. package/examples/minimal-paper/main.tex +23 -0
  153. package/package.json +66 -0
  154. package/src/backend/olcli/LICENSE +21 -0
  155. package/src/backend/olcli/README.md +26 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 overleaf-codex contributors
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.
package/NOTICE.md ADDED
@@ -0,0 +1,25 @@
1
+ # Notices
2
+
3
+ `overleaf-codex` / `olcx` is an independent project.
4
+
5
+ ## aloth/olcli
6
+
7
+ `olcx` includes backend-private code copied or adapted from `@aloth/olcli@0.5.0`.
8
+
9
+ - Project: `@aloth/olcli`
10
+ - Repository: https://github.com/aloth/olcli
11
+ - Version: `0.5.0`
12
+ - Tag: `v0.5.0`
13
+ - Commit: `524c30b11328a847a9c0bcf4447d2b3468160f8c`
14
+ - npm tarball: https://registry.npmjs.org/@aloth/olcli/-/olcli-0.5.0.tgz
15
+ - Copied/adapted file: `src/client.ts` -> `src/backend/olcli/client.ts`
16
+ - Author: Alexander Loth <alex@alexloth.com>
17
+ - Copyright: Copyright (c) 2026 Alexander Loth
18
+ - License: MIT
19
+
20
+ The copied upstream MIT license text is preserved at `src/backend/olcli/LICENSE`.
21
+ The backend-private source directory documents adaptation notes in
22
+ `src/backend/olcli/README.md`.
23
+
24
+ `olcx` is not affiliated with, endorsed by, or maintained by Overleaf or `olcli`.
25
+ `olcx` is not an official Overleaf project and is not an official `olcli` project.
package/README.md ADDED
@@ -0,0 +1,217 @@
1
+ <p align="center">
2
+ <img src="assets/olcx-mark.svg" alt="olcx" width="96" height="96">
3
+ </p>
4
+
5
+ # overleaf-codex
6
+
7
+ [![CI](https://github.com/umiskky/overleaf-codex/actions/workflows/ci.yml/badge.svg)](https://github.com/umiskky/overleaf-codex/actions/workflows/ci.yml)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
9
+ [![Status](https://img.shields.io/badge/status-v1--rc--local--gates-blue.svg)](#current-status)
10
+
11
+ `overleaf-codex` provides the `olcx` CLI for writing LaTeX papers locally while
12
+ using a bound Overleaf project for remote compilation.
13
+
14
+ The workflow is CLI-first:
15
+
16
+ - edit the paper locally in VS Code or another editor;
17
+ - keep source history in local Git;
18
+ - bind one paper repository to one Overleaf project by default;
19
+ - store Overleaf authorization in project-local ignored files;
20
+ - sync without silently overwriting local or remote changes;
21
+ - compile on Overleaf and download the PDF to a stable local path.
22
+
23
+ `olcx` does not require a local LaTeX installation for the core workflow. It does
24
+ not include a VS Code extension; `olcx init` creates or repairs local VS Code
25
+ settings and tasks by default.
26
+
27
+ ## Install
28
+
29
+ From npm:
30
+
31
+ ```bash
32
+ npm install -g overleaf-codex
33
+ olcx --help
34
+ ```
35
+
36
+ From a checkout:
37
+
38
+ ```bash
39
+ npm install
40
+ npm run build
41
+ npm run dev -- --help
42
+ ```
43
+
44
+ ## First Run
45
+
46
+ Run these commands from the root of a paper repository:
47
+
48
+ ```bash
49
+ git init
50
+ olcx init --project https://www.overleaf.com/project/<overleaf-project-id>
51
+ olcx endpoint status
52
+ olcx endpoint test
53
+ olcx auth
54
+ olcx status
55
+ olcx doctor
56
+ olcx sync --dry-run
57
+ olcx sync
58
+ olcx compile
59
+ olcx watch
60
+ ```
61
+
62
+ `olcx init` creates `.olcx/config.json`, updates local ignore rules, and merges
63
+ `.vscode/settings.json` and `.vscode/tasks.json`. The generated VS Code tasks
64
+ cover status, doctor, sync dry-run, sync apply, compile, watch, and read-only
65
+ endpoint checks.
66
+
67
+ For headless shells or CI-like terminals, provide the session cookie through an
68
+ environment variable instead of an interactive prompt:
69
+
70
+ ```bash
71
+ export OLCX_OVERLEAF_SESSION='<copied-session-cookie>'
72
+ olcx auth --from-env OLCX_OVERLEAF_SESSION
73
+ unset OLCX_OVERLEAF_SESSION
74
+ ```
75
+
76
+ `olcx auth` writes only project-local authorization:
77
+
78
+ ```text
79
+ .olcx/auth.local.json
80
+ ```
81
+
82
+ That file is ignored by Git and must not be committed. `olcx` must not store
83
+ Overleaf passwords.
84
+
85
+ ## Current Status
86
+
87
+ v1 is a release candidate. Local gates are tracked in
88
+ [docs/release-notes-v1.md](docs/release-notes-v1.md); stable release remains
89
+ blocked until a sanitized disposable real Overleaf E2E pass is recorded.
90
+
91
+ The implemented command surface is:
92
+
93
+ ```bash
94
+ olcx auth
95
+ olcx init --project <overleaf-url-or-id>
96
+ olcx endpoint status
97
+ olcx endpoint test
98
+ olcx endpoint set cn
99
+ olcx endpoint test --apply
100
+ olcx sync --dry-run
101
+ olcx sync
102
+ olcx compile
103
+ olcx watch
104
+ olcx status
105
+ olcx doctor
106
+ ```
107
+
108
+ The detailed CLI behavior, output, redaction, and exit-code contract is
109
+ documented in [docs/cli-behavior.md](docs/cli-behavior.md).
110
+
111
+ Endpoint testing is read-only and manual by default. `olcx endpoint test` probes
112
+ public reachability for `https://www.overleaf.com/project` and
113
+ `https://cn.overleaf.com/project`; it does not sync, upload, compile, validate
114
+ auth, or modify remote projects. The configured endpoint is stored as
115
+ `overleaf.baseUrl` in `.olcx/config.json`, and `olcx endpoint test --apply` is
116
+ the only automatic selection mode.
117
+
118
+ ## Sync And Compile
119
+
120
+ `olcx sync --dry-run` shows the planned upload, download, and delete actions.
121
+ `olcx sync` applies a clean plan. If the same path changed locally and remotely,
122
+ `olcx` stops with `SYNC_CONFLICT` and writes a conflict report under
123
+ `.olcx/state/conflicts.json`; it must not silently overwrite either side.
124
+
125
+ Manual conflict recovery:
126
+
127
+ ```bash
128
+ olcx sync --dry-run
129
+ cat .olcx/state/conflicts.json
130
+ olcx sync
131
+ ```
132
+
133
+ `olcx compile` asks Overleaf to compile the bound project and downloads the PDF:
134
+
135
+ ```text
136
+ build/overleaf/main.pdf
137
+ ```
138
+
139
+ You can override that path with `olcx compile --pdf build/overleaf/main.pdf`.
140
+ `olcx watch` pauses on `SYNC_CONFLICT` or compile failure and prints the manual
141
+ command to run next.
142
+
143
+ ## Documentation
144
+
145
+ - [docs/usage.md](docs/usage.md) covers the full install-to-watch workflow.
146
+ - [docs/auth.md](docs/auth.md) covers interactive and headless auth.
147
+ - [docs/sync.md](docs/sync.md) covers dry runs, conflicts, and safe recovery.
148
+ - [docs/compile.md](docs/compile.md) covers remote compile and PDF output.
149
+ - [docs/endpoint.md](docs/endpoint.md) covers `www`/`cn` endpoint selection.
150
+ - [docs/troubleshooting.md](docs/troubleshooting.md) lists diagnosis commands.
151
+ - [docs/npm-packaging.md](docs/npm-packaging.md) explains package contents.
152
+ - [docs/release-gates.md](docs/release-gates.md) explains release checks.
153
+ - [docs/release-notes-v1.md](docs/release-notes-v1.md) records the v1 RC status, release notes, known limitations, and stable-release approval rule.
154
+
155
+ See the [minimal example paper](examples/minimal-paper/README.md) for a
156
+ sanitized project layout with `.olcx/config.json`, an auth-file shape example,
157
+ the default `build/overleaf/main.pdf` output path, and the `olcx watch` flow.
158
+ Replace `<overleaf-project-id>` with your own project reference through
159
+ `olcx init --project https://www.overleaf.com/project/<overleaf-project-id>`.
160
+
161
+ ## Relationship to olcli
162
+
163
+ `olcx` vendors backend-private code copied or adapted from `@aloth/olcli@0.5.0`
164
+ as an Overleaf backend foundation.
165
+
166
+ - Source repository: https://github.com/aloth/olcli
167
+ - Source tag: `v0.5.0`
168
+ - Source commit: `524c30b11328a847a9c0bcf4447d2b3468160f8c`
169
+ - Copied/adapted file: upstream `src/client.ts` to `src/backend/olcli/client.ts`
170
+ - License: MIT
171
+ - Copyright: Copyright (c) 2026 Alexander Loth
172
+
173
+ Users install and run `olcx`; they do not need to install `olcli` separately.
174
+ `@aloth/olcli` is not a runtime dependency of this package.
175
+
176
+ `olcx` is not an official Overleaf project and is not an official `olcli` project.
177
+ It is not affiliated with, endorsed by, or maintained by Overleaf or `olcli`.
178
+
179
+ ## Security Model
180
+
181
+ `olcx` must never commit Overleaf credentials, cookies, passwords, or local
182
+ session files. Keep `.olcx/auth.local.json`, `*.local.json`, and
183
+ `*.secret.json` ignored. See [docs/security.md](docs/security.md) and
184
+ [SECURITY.md](SECURITY.md).
185
+
186
+ ## Development
187
+
188
+ Requirements:
189
+
190
+ - Node.js 20 or newer
191
+ - npm 10 or newer
192
+
193
+ Useful commands:
194
+
195
+ ```bash
196
+ npm install
197
+ npm run build
198
+ npm run typecheck
199
+ npm test
200
+ OLCX_E2E_IGNORE_LOCAL_ENV=1 OLCX_E2E_ENABLE_REAL=0 npm run test:e2e:real
201
+ npm audit --audit-level=high
202
+ npm run prepublish:check
203
+ ```
204
+
205
+ ## Contributing
206
+
207
+ This project is intended to be open source and community-maintained. Before
208
+ contributing, read:
209
+
210
+ - [CONTRIBUTING.md](CONTRIBUTING.md)
211
+ - [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
212
+ - [SECURITY.md](SECURITY.md)
213
+ - [ROADMAP.md](ROADMAP.md)
214
+
215
+ ## License
216
+
217
+ MIT. See [LICENSE](LICENSE) and [NOTICE.md](NOTICE.md).
@@ -0,0 +1,22 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-labelledby="title desc">
2
+ <title id="title">olcx mark</title>
3
+ <desc id="desc">A document, code brackets, and a leaf-shaped Overleaf reference mark.</desc>
4
+ <defs>
5
+ <linearGradient id="paper" x1="28" y1="18" x2="98" y2="112" gradientUnits="userSpaceOnUse">
6
+ <stop stop-color="#f8fafc"/>
7
+ <stop offset="1" stop-color="#dbeafe"/>
8
+ </linearGradient>
9
+ <linearGradient id="leaf" x1="74" y1="28" x2="105" y2="79" gradientUnits="userSpaceOnUse">
10
+ <stop stop-color="#34d399"/>
11
+ <stop offset="1" stop-color="#059669"/>
12
+ </linearGradient>
13
+ </defs>
14
+ <rect width="128" height="128" rx="24" fill="#0f172a"/>
15
+ <path d="M35 18h40l20 20v72H35z" fill="url(#paper)"/>
16
+ <path d="M75 18v20h20z" fill="#bfdbfe"/>
17
+ <path d="M50 57 37 69l13 12" fill="none" stroke="#2563eb" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/>
18
+ <path d="M78 57 91 69 78 81" fill="none" stroke="#2563eb" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/>
19
+ <path d="M68 53 58 86" fill="none" stroke="#0f172a" stroke-width="7" stroke-linecap="round"/>
20
+ <path d="M85 32c18 2 27 17 18 31-8 12-27 13-38 2 3-18 10-29 20-33z" fill="url(#leaf)"/>
21
+ <path d="M68 65c11-4 21-12 29-25" fill="none" stroke="#ecfdf5" stroke-width="5" stroke-linecap="round"/>
22
+ </svg>
@@ -0,0 +1,19 @@
1
+ import { type ProjectAuth } from "./types.js";
2
+ export interface ResolveProjectAuthOptions {
3
+ env?: Record<string, string | undefined>;
4
+ envVarName?: string;
5
+ now?: () => Date;
6
+ }
7
+ export declare function getProjectAuthPath(projectRoot: string): string;
8
+ export declare function validateProjectAuth(value: unknown): ProjectAuth;
9
+ export declare function readProjectAuth(projectRoot: string): Promise<ProjectAuth>;
10
+ export declare function writeProjectAuth(projectRoot: string, auth: ProjectAuth): Promise<void>;
11
+ export declare function deleteProjectAuth(projectRoot: string): Promise<boolean>;
12
+ export declare function resolveProjectAuth(projectRoot: string, options?: ResolveProjectAuthOptions): Promise<ProjectAuth>;
13
+ export declare function summarizeProjectAuth(auth: ProjectAuth): {
14
+ schemaVersion: 1;
15
+ accountLabel: string;
16
+ source: ProjectAuth["source"];
17
+ updatedAt: string;
18
+ hasSessionCookie: boolean;
19
+ };
@@ -0,0 +1,163 @@
1
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { OLCX_DIR } from "../config/types.js";
4
+ import { createOlcxError } from "../errors.js";
5
+ import { DEFAULT_PROJECT_AUTH_ENV_VAR, PROJECT_AUTH_FILENAME, } from "./types.js";
6
+ import { redactForStatus } from "./redact.js";
7
+ const FORBIDDEN_AUTH_KEYS = new Set(["password", "passwd", "cookie", "token", "auth", "authorization", "csrf"]);
8
+ export function getProjectAuthPath(projectRoot) {
9
+ return join(projectRoot, OLCX_DIR, PROJECT_AUTH_FILENAME);
10
+ }
11
+ export function validateProjectAuth(value) {
12
+ assertRecord(value, "auth");
13
+ assertNoForbiddenAuthKeys(value, "auth");
14
+ if (value.schemaVersion !== 1) {
15
+ throw new Error("schemaVersion must be 1");
16
+ }
17
+ const sessionCookie = requireNonEmptyString(value.sessionCookie, "sessionCookie");
18
+ const updatedAt = requireIsoTimestamp(value.updatedAt, "updatedAt");
19
+ const source = requireAuthSource(value.source);
20
+ const auth = {
21
+ schemaVersion: 1,
22
+ sessionCookie,
23
+ updatedAt,
24
+ source,
25
+ };
26
+ if (value.accountLabel !== undefined) {
27
+ auth.accountLabel = requireNonEmptyString(value.accountLabel, "accountLabel");
28
+ }
29
+ return auth;
30
+ }
31
+ export async function readProjectAuth(projectRoot) {
32
+ const path = getProjectAuthPath(projectRoot);
33
+ let raw;
34
+ try {
35
+ raw = await readFile(path, "utf8");
36
+ }
37
+ catch (error) {
38
+ if (isNodeError(error, "ENOENT")) {
39
+ throw createOlcxError({
40
+ code: "PROJECT_AUTH_NOT_FOUND",
41
+ message: "Project auth was not found.",
42
+ hint: "Authenticate this paper repository before using Overleaf-backed operations.",
43
+ details: { path: ".olcx/auth.local.json" },
44
+ cause: error,
45
+ });
46
+ }
47
+ throw error;
48
+ }
49
+ try {
50
+ return validateProjectAuth(JSON.parse(raw));
51
+ }
52
+ catch (error) {
53
+ throw createOlcxError({
54
+ code: "PROJECT_AUTH_INVALID",
55
+ message: "Project auth is invalid.",
56
+ hint: "Re-authenticate this paper repository to regenerate .olcx/auth.local.json.",
57
+ details: {
58
+ path: ".olcx/auth.local.json",
59
+ reason: error instanceof Error ? error.message : "Invalid JSON or schema.",
60
+ },
61
+ cause: error,
62
+ });
63
+ }
64
+ }
65
+ export async function writeProjectAuth(projectRoot, auth) {
66
+ const validated = validateProjectAuth(auth);
67
+ await mkdir(join(projectRoot, OLCX_DIR), { recursive: true });
68
+ await writeFile(getProjectAuthPath(projectRoot), `${JSON.stringify(validated, null, 2)}\n`, "utf8");
69
+ }
70
+ export async function deleteProjectAuth(projectRoot) {
71
+ try {
72
+ await rm(getProjectAuthPath(projectRoot));
73
+ return true;
74
+ }
75
+ catch (error) {
76
+ if (isNodeError(error, "ENOENT")) {
77
+ return false;
78
+ }
79
+ throw error;
80
+ }
81
+ }
82
+ export async function resolveProjectAuth(projectRoot, options = {}) {
83
+ const env = options.env ?? process.env;
84
+ const envVarName = options.envVarName ?? DEFAULT_PROJECT_AUTH_ENV_VAR;
85
+ const envValue = env[envVarName];
86
+ if (typeof envValue === "string" && envValue.trim().length > 0) {
87
+ return validateProjectAuth({
88
+ schemaVersion: 1,
89
+ sessionCookie: envValue,
90
+ updatedAt: (options.now ?? (() => new Date()))().toISOString(),
91
+ source: "env",
92
+ });
93
+ }
94
+ return readProjectAuth(projectRoot);
95
+ }
96
+ export function summarizeProjectAuth(auth) {
97
+ return {
98
+ schemaVersion: auth.schemaVersion,
99
+ accountLabel: summarizeAccountLabel(auth.accountLabel),
100
+ source: auth.source,
101
+ updatedAt: auth.updatedAt,
102
+ hasSessionCookie: auth.sessionCookie.trim().length > 0,
103
+ };
104
+ }
105
+ function summarizeAccountLabel(accountLabel) {
106
+ if (accountLabel === undefined || accountLabel.trim().length === 0) {
107
+ return "unknown";
108
+ }
109
+ const trimmed = accountLabel.trim();
110
+ const redacted = redactForStatus(trimmed);
111
+ if (redacted !== trimmed) {
112
+ return redacted;
113
+ }
114
+ if (/[^\w .@+-]/.test(trimmed)) {
115
+ return "<redacted-account>";
116
+ }
117
+ return trimmed;
118
+ }
119
+ function assertRecord(value, field) {
120
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
121
+ throw new Error(`${field} must be an object`);
122
+ }
123
+ }
124
+ function requireNonEmptyString(value, field) {
125
+ if (typeof value !== "string" || value.trim().length === 0) {
126
+ throw new Error(`${field} must be a non-empty string`);
127
+ }
128
+ return value;
129
+ }
130
+ function requireIsoTimestamp(value, field) {
131
+ const timestamp = requireNonEmptyString(value, field);
132
+ const parsed = Date.parse(timestamp);
133
+ if (Number.isNaN(parsed)) {
134
+ throw new Error(`${field} must be a parseable ISO timestamp`);
135
+ }
136
+ return timestamp;
137
+ }
138
+ function requireAuthSource(value) {
139
+ if (value !== "interactive" && value !== "cli-option" && value !== "env") {
140
+ throw new Error('source must be "interactive", "cli-option", or "env"');
141
+ }
142
+ return value;
143
+ }
144
+ function assertNoForbiddenAuthKeys(value, field) {
145
+ if (Array.isArray(value)) {
146
+ value.forEach((entry, index) => assertNoForbiddenAuthKeys(entry, `${field}[${index}]`));
147
+ return;
148
+ }
149
+ if (!value || typeof value !== "object") {
150
+ return;
151
+ }
152
+ for (const [key, entry] of Object.entries(value)) {
153
+ const normalizedKey = key.toLowerCase();
154
+ if (normalizedKey !== "sessioncookie" && FORBIDDEN_AUTH_KEYS.has(normalizedKey)) {
155
+ throw new Error(`${field}.${key} is not allowed in project auth`);
156
+ }
157
+ assertNoForbiddenAuthKeys(entry, `${field}.${key}`);
158
+ }
159
+ }
160
+ function isNodeError(error, code) {
161
+ return typeof error === "object" && error !== null && error.code === code;
162
+ }
163
+ //# sourceMappingURL=projectAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectAuth.js","sourceRoot":"","sources":["../../src/auth/projectAuth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function redactForStatus(value: unknown): string;
2
+ export declare const redactAuth: typeof redactForStatus;
3
+ export declare const redactConfig: typeof redactForStatus;
@@ -0,0 +1,7 @@
1
+ import { redactSensitive } from "../cli-behavior.js";
2
+ export function redactForStatus(value) {
3
+ return redactSensitive(value);
4
+ }
5
+ export const redactAuth = redactForStatus;
6
+ export const redactConfig = redactForStatus;
7
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/auth/redact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,eAAe,CAAC;AAC1C,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC"}
@@ -0,0 +1,10 @@
1
+ export declare const PROJECT_AUTH_FILENAME: "auth.local.json";
2
+ export declare const PROJECT_AUTH_PATH: ".olcx/auth.local.json";
3
+ export declare const DEFAULT_PROJECT_AUTH_ENV_VAR: "OLCX_OVERLEAF_SESSION";
4
+ export interface ProjectAuth {
5
+ schemaVersion: 1;
6
+ accountLabel?: string;
7
+ sessionCookie: string;
8
+ updatedAt: string;
9
+ source: "interactive" | "cli-option" | "env";
10
+ }
@@ -0,0 +1,4 @@
1
+ export const PROJECT_AUTH_FILENAME = "auth.local.json";
2
+ export const PROJECT_AUTH_PATH = ".olcx/auth.local.json";
3
+ export const DEFAULT_PROJECT_AUTH_ENV_VAR = "OLCX_OVERLEAF_SESSION";
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,iBAA0B,CAAC;AAChE,MAAM,CAAC,MAAM,iBAAiB,GAAG,uBAAgC,CAAC;AAClE,MAAM,CAAC,MAAM,4BAA4B,GAAG,uBAAgC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { createOlcliOverleafBackend } from "./overleafBackend.js";
2
+ export type { OlcliBackendOptions } from "./overleafBackend.js";
3
+ import type { OlcliBackendOptions } from "./overleafBackend.js";
4
+ import type { OverleafBackend } from "./types.js";
5
+ export type { BackendAccount, BackendAuthInput, BackendCompileInput, BackendFastCompileRestoreResult, BackendFastCompileRestoreStatus, BackendFastCompileSession, BackendFileInput, BackendProjectInput, BackendUploadInput, CompileLogEntry, CompileResult, OverleafBackend, RemoteFile, } from "./types.js";
6
+ export type OverleafBackendFactory = (options: OlcliBackendOptions) => OverleafBackend;
@@ -0,0 +1,2 @@
1
+ export { createOlcliOverleafBackend } from "./overleafBackend.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC"}