arca-siradig 1.0.0

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.
Files changed (49) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +311 -0
  3. package/dist/src/arca/deductions.d.ts +71 -0
  4. package/dist/src/arca/deductions.js +636 -0
  5. package/dist/src/arca/employees.d.ts +10 -0
  6. package/dist/src/arca/employees.js +80 -0
  7. package/dist/src/arca/form.d.ts +39 -0
  8. package/dist/src/arca/form.js +143 -0
  9. package/dist/src/arca/http.d.ts +14 -0
  10. package/dist/src/arca/http.js +108 -0
  11. package/dist/src/arca/menu.d.ts +6 -0
  12. package/dist/src/arca/menu.js +36 -0
  13. package/dist/src/arca/personal-data.d.ts +4 -0
  14. package/dist/src/arca/personal-data.js +62 -0
  15. package/dist/src/arca/persons.d.ts +11 -0
  16. package/dist/src/arca/persons.js +115 -0
  17. package/dist/src/arca/receipt-types.d.ts +4 -0
  18. package/dist/src/arca/receipt-types.js +39 -0
  19. package/dist/src/arca/session.d.ts +27 -0
  20. package/dist/src/arca/session.js +165 -0
  21. package/dist/src/arca/submission.d.ts +22 -0
  22. package/dist/src/arca/submission.js +140 -0
  23. package/dist/src/arca/submitted-forms.d.ts +12 -0
  24. package/dist/src/arca/submitted-forms.js +54 -0
  25. package/dist/src/cli/errors.d.ts +1 -0
  26. package/dist/src/cli/errors.js +11 -0
  27. package/dist/src/cli/help.d.ts +6 -0
  28. package/dist/src/cli/help.js +301 -0
  29. package/dist/src/cli/index.d.ts +2 -0
  30. package/dist/src/cli/index.js +810 -0
  31. package/dist/src/cli/options.d.ts +120 -0
  32. package/dist/src/cli/options.js +419 -0
  33. package/dist/src/cli/prompts.d.ts +9 -0
  34. package/dist/src/cli/prompts.js +99 -0
  35. package/dist/src/cli/render.d.ts +13 -0
  36. package/dist/src/cli/render.js +262 -0
  37. package/dist/src/cli/structured-output.d.ts +4 -0
  38. package/dist/src/cli/structured-output.js +92 -0
  39. package/dist/src/files/pdf.d.ts +3 -0
  40. package/dist/src/files/pdf.js +43 -0
  41. package/dist/src/files/private.d.ts +4 -0
  42. package/dist/src/files/private.js +21 -0
  43. package/dist/src/security/errors.d.ts +2 -0
  44. package/dist/src/security/errors.js +22 -0
  45. package/dist/src/session/store.d.ts +15 -0
  46. package/dist/src/session/store.js +35 -0
  47. package/dist/src/types.d.ts +106 -0
  48. package/dist/src/types.js +1 -0
  49. package/package.json +59 -0
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 ARCA SiRADIG contributors
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,311 @@
1
+ # ARCA SiRADIG CLI
2
+
3
+ CLI for signing in to ARCA and managing **SiRADIG - Trabajador** Form 572 drafts:
4
+ inspect personal data, employers and deductions; add or remove supported receipts;
5
+ preview, print and submit a form to the employer.
6
+
7
+ ## Installation
8
+
9
+ Use Node.js 20.17+ (20.x), 22.13+ (22.x), or 23.5+. Run the published CLI with
10
+ `npx`:
11
+
12
+ ```bash
13
+ npx arca-siradig --help
14
+ ```
15
+
16
+ Before the first login, install the Chromium version required by the CLI's Playwright
17
+ dependency. The browser is cached for subsequent commands:
18
+
19
+ ```bash
20
+ npx --yes --package=arca-siradig playwright install chromium
21
+ npx arca-siradig login
22
+ npx arca-siradig form summary --period 2026
23
+ ```
24
+
25
+ Alternatively, install the command globally:
26
+
27
+ ```bash
28
+ npm install --global arca-siradig
29
+ arca-siradig --help
30
+ ```
31
+
32
+ For development from a local checkout:
33
+
34
+ ```bash
35
+ npm ci
36
+ npx playwright install chromium
37
+ npm run build
38
+ ```
39
+
40
+ Optionally create a local `.env` file:
41
+
42
+ ```bash
43
+ ARCA_CUIT=<your-cuit-or-cuil>
44
+ ARCA_PASSWORD=<your-tax-password>
45
+ ```
46
+
47
+ `.env` and its local variants are ignored by Git; `.env.example` contains empty defaults.
48
+ The CLI uses populated values as prompt defaults; the password is masked and can be
49
+ accepted by pressing `enter`. Prefer the interactive password prompt. If you create a
50
+ populated `.env`, keep it private (for example, `chmod 600 .env` on macOS/Linux).
51
+
52
+ ## Usage
53
+
54
+ Examples below use `arca-siradig` directly after a global installation or local link.
55
+ When using `npx`, prefix each command with `npx`.
56
+
57
+ To make a local checkout available as a command outside its folder, build it and link it:
58
+
59
+ ```bash
60
+ npm run build
61
+ npm link
62
+ arca-siradig --help
63
+ ```
64
+
65
+ This links the local package without publishing it to npm. Run `npm run build` again after
66
+ changing the TypeScript sources. A local assistant with terminal access can invoke this
67
+ command and reuse the session created by `arca-siradig login` under the same OS user.
68
+ Use `--format=json` for supported read commands. The CLI accepts structured receipt fields
69
+ through `form deductions add-item-receipt`; it does not extract fields from PDF or image files.
70
+ An assistant must interpret the document before calling that command.
71
+
72
+ ```bash
73
+ npm run arca-siradig
74
+ ```
75
+
76
+ This prints help by default. Append `--help` to a command or subcommand to see its options,
77
+ without signing in or executing the command:
78
+
79
+ ```bash
80
+ arca-siradig login --help
81
+ arca-siradig employees show --help
82
+ arca-siradig form deductions --help
83
+ ```
84
+
85
+ Playwright runs headless by default. To log in with a visible browser, pass:
86
+
87
+ ```bash
88
+ npm run arca-siradig -- login --headless false
89
+ ```
90
+
91
+ ## Commands
92
+
93
+ ```bash
94
+ npm run arca-siradig -- login
95
+ npm run arca-siradig -- logout
96
+ npm run arca-siradig -- persons list
97
+ npm run arca-siradig -- persons select <id|name>
98
+ npm run arca-siradig -- persons list --format=json
99
+ npm run arca-siradig -- personal-data show [--person "<id|name>"]
100
+ npm run arca-siradig -- employees list [--person "<id|name>"]
101
+ npm run arca-siradig -- employees show [--person "<id|name>"] --employee-cuit <cuit>
102
+ npm run arca-siradig -- form deductions list [--person "<id|name>"]
103
+ npm run arca-siradig -- form deductions list-receipt-types
104
+ npm run arca-siradig -- form deductions show <id> [--person "<id|name>"]
105
+ npm run arca-siradig -- form deductions add-item --period=<YYYY> --type=<type> --cuit=<provider-cuit> --month=<1-12> --amount=<amount>
106
+ npm run arca-siradig -- form deductions add-item-receipt --period=<YYYY> --type=<type> --cuit=<provider-cuit> --month=<1-12> --amount=<amount> --receipt-type=<id> --date=<YYYY-MM-DD> --number=<number>
107
+ npm run arca-siradig -- form deductions add-item-receipt --period=<YYYY> --type=gastos-medicos --cuit=<provider-cuit> --month=<1-12> --amount=<amount> --reimbursed-amount=<amount> --receipt-type=<id> --date=<YYYY-MM-DD> --number=<number>
108
+ npm run arca-siradig -- form deductions remove-item-receipt --period=<YYYY> --cuit=<provider-cuit> --number=<number>
109
+ npm run arca-siradig -- --interactive
110
+ ```
111
+
112
+ `login` prompts for missing CUIT/CUIL or password values. After a successful login, the CLI
113
+ stores Playwright session state in `~/.arca-siradig/session.json` and never stores the
114
+ password. It also selects the first available SiRADIG person automatically and stores that
115
+ selection. If no people are listed, the CLI keeps the session but asks you to add a person in
116
+ ARCA before continuing.
117
+
118
+ `--cuit` and `--password` are available for automation, but password arguments can be
119
+ recorded in shell history and exposed in process listings. Use the prompt for manual login.
120
+
121
+ Login uses the SiRADIG fiscal-key entry linked from `https://www.afip.gob.ar/572web/`
122
+ (`login.xhtml?action=SYSTEM&system=radig`). If authentication opens SiRADIG directly,
123
+ the CLI skips the portal service selector. Portal navigation remains a fallback.
124
+
125
+ `logout` removes the stored session file.
126
+
127
+ `persons list` reuses the stored session. If there is no session or ARCA has expired it, run
128
+ `arca-siradig login` again. The default output format is text; pass `--format=json` for JSON.
129
+
130
+ `persons select` accepts either the person id or the person name shown by `persons list`.
131
+
132
+ `personal-data show`, `employees list`, `employees show`, `form deductions list`, and
133
+ `form deductions show` reuse the stored session and will use the stored selected person when
134
+ available. You can still pass `--person` to override it. All five commands support
135
+ `--format=text|json`.
136
+
137
+ `employees list` and `form deductions list` first read the portal's embedded JSON through
138
+ authenticated HTTP requests, reducing browser navigation. The employer lookup for
139
+ `employees show` uses the same path. If ARCA changes the response or the session expires,
140
+ the CLI falls back to its browser flow. Login and person selection still use Playwright.
141
+
142
+ `form deductions list-receipt-types` prints the hardcoded `cmpTipo` catalog used by the
143
+ portal. Text output shows an `ID`/`Tipo` table and JSON output returns `{ id, name }`
144
+ objects.
145
+
146
+ `form deductions show <id>` first resolves the item from the grouped deductions list, then
147
+ opens the read-only detail page for that exact record. Text output mirrors the web view with
148
+ entity, period, monthly detail, and receipts sections. JSON output is structured in English
149
+ with normalized months, amounts, receipt dates, and numeric receipt type ids.
150
+
151
+ `form deductions add-item` and `form deductions add-item-receipt` identify the target deduction by
152
+ provider CUIT plus deduction type. For monthly-detail deductions, use the type shown by
153
+ `form deductions list` and the provider CUIT shown in the same row.
154
+
155
+ `form deductions add-item-receipt --type=gastos-medicos` loads a medical expense receipt by
156
+ provider CUIT and month. If the same provider/month already exists in `form deductions list`, the
157
+ CLI opens that item; otherwise it opens `verGastosMedicos.do`, fills the provider CUIT,
158
+ selects the month, adds the receipt, and saves the draft.
159
+
160
+ `form deductions remove-item-receipt` currently removes `gastos-medicos` receipts by provider
161
+ CUIT and receipt number. It searches all matching provider entries, removes the matching
162
+ receipt row, and saves the draft.
163
+
164
+ ## Fiscal Forms
165
+
166
+ ```bash
167
+ arca-siradig form show --period 2026 --format=json
168
+ arca-siradig form deductions list --period 2026 --format=json
169
+ arca-siradig form summary --period 2026
170
+ arca-siradig form summary --period 2026 --format=json
171
+ arca-siradig form print --period 2026 --path ./f572-2026.pdf
172
+ arca-siradig form print --period 2026 --path ./
173
+ ```
174
+
175
+ All form commands accept `--person <id|name>` and otherwise use the stored selected person.
176
+ Read commands may omit `--period`: they report the fiscal year actually selected by ARCA,
177
+ without assuming that it is the latest year. An explicit period is selected through the
178
+ worker entry and verified against the portal breadcrumb; unavailable periods fail.
179
+ These commands access the current form draft, not historical submitted versions.
180
+
181
+ `form show` reports person and period. `form summary` reads the official HTML draft preview,
182
+ including presentation character, withholding agent, section tables, and the totals displayed
183
+ by ARCA. It preserves ARCA's amounts and labels without recalculating tax or deductible limits.
184
+ The console summary highlights official totals and groups monthly amounts by category and
185
+ provider. Empty sections are condensed rather than printing their empty table headers.
186
+ Colors are enabled for terminals and disabled for redirected output or `NO_COLOR`.
187
+
188
+ `form print` uses the official **Imprimir Borrador** download and validates that it is a PDF.
189
+ `--path` accepts a PDF filename or a directory (`./`, an existing directory, a path ending
190
+ in `/`, or a new path without an extension). Directories use `f572-<year>-borrador.pdf`.
191
+ Parent directories are created as needed. Existing names receive ` (1)`, ` (2)`, etc.
192
+ before the extension, including explicit filenames. Files use private permissions and are
193
+ never overwritten; the CLI always prints the absolute path of the saved file.
194
+
195
+ Changes (`add-item`, `add-item-receipt`, `remove-item-receipt`) require `--period`.
196
+ Receipt dates must belong to that year. The CLI verifies the represented
197
+ person and fiscal year before changing a form. Session refresh restores this context for
198
+ form reads before retrying navigation.
199
+
200
+ `form deductions list` JSON is `{ period, person: { id, name }, deductions: [...] }`;
201
+ detail JSON is
202
+ `{ period, person: { id, name }, deduction: {...} }`. Text output includes person and year.
203
+ The static receipt-type catalog retains its existing output and does not accept a period.
204
+
205
+ ### Submit to the employer
206
+
207
+ ```bash
208
+ arca-siradig form submit --period 2026
209
+ arca-siradig form submit --period 2026 --aceptar
210
+ arca-siradig form submit --period 2026 --aceptar --format=json
211
+ ```
212
+
213
+ `form submit` shows the official draft summary, opens ARCA's confirmation dialog, and asks
214
+ **Aceptar — Generar Presentación** or **Cancelar** in the terminal. Cancel is the default;
215
+ interrupting the prompt also cancels. `--aceptar` skips the terminal question and confirms
216
+ **Generar Presentación** directly. Submission always requires `--period` and supports
217
+ `--person`. Without a terminal, `--aceptar` is required.
218
+
219
+ The CLI verifies person and year again immediately before the final click and never retries
220
+ that click automatically. Results report `submitted`, `cancelled`, `rejected`, or
221
+ `unconfirmed`. Success requires a positive acknowledgement or a newly registered
222
+ presentation. When that wording is unknown, the CLI checks **Consulta de Formularios Enviados**
223
+ against a snapshot taken immediately before the final click. It verifies person and
224
+ period and requires exactly one new record with the next presentation number; a
225
+ presentation already present before the attempt never confirms success. A confirmed
226
+ history result includes the presentation number, description, and sending date.
227
+ If neither check can confirm the result, inspect that history in ARCA before trying
228
+ again. The message includes the final screen URL without query parameters and the
229
+ reason history could not confirm the attempt. Rejected or unconfirmed results exit with code 1.
230
+ The summary and prompt use stderr so JSON results remain a single stdout object.
231
+
232
+ Confirmation and result handling have been tested with mocked HTML. Read-only live
233
+ inspection confirmed the history structure after a user-initiated CLI submission;
234
+ development did not generate another live presentation.
235
+
236
+ ## Interactive Flow
237
+
238
+ Run the current read-only interactive flow with:
239
+
240
+ ```bash
241
+ npm run arca-siradig -- --interactive
242
+ ```
243
+
244
+ The flow:
245
+
246
+ 1. Prompts for CUIT/CUIL and tax password.
247
+ 2. Signs in to ARCA.
248
+ 3. Prompts again if ARCA rejects the credentials.
249
+ 4. Opens the `SiRADIG - Trabajador` service.
250
+ 5. Automatically accepts the draft reminder if it appears.
251
+ 6. Lists the people available to represent.
252
+ 7. Selects the person for the current browser session; interactive mode does not persist it.
253
+ 8. Shows the main menu with all actions disabled except `Datos Personales`.
254
+ 9. Shows personal data grouped by section.
255
+
256
+ ## Scripts
257
+
258
+ ```bash
259
+ npm run build
260
+ npm run check
261
+ npm run format
262
+ npm test
263
+ ```
264
+
265
+ ## Development Inspection
266
+
267
+ For portal markup changes or new read-only features, use:
268
+
269
+ ```bash
270
+ npx tsx scripts/inspect-live.ts
271
+ ```
272
+
273
+ This opens visible Chromium, uses credentials from `.env`, navigates read-only through the
274
+ worker flow, and writes HTML summaries and screenshots to a randomly named directory under
275
+ the OS temporary directory. The path is printed even if inspection fails. On macOS/Linux,
276
+ the directory has mode `0700` and files have mode `0600` from creation.
277
+ Captures include personal tax data; keep them private, remove them when finished, and build
278
+ test fixtures from synthetic data instead of copying captured responses.
279
+
280
+ ## V1 Limitations
281
+
282
+ - Writes support monthly deduction items and receipts; medical expense receipts also support removal.
283
+ - `form submit` sends a presentation to the employer after confirmation, or with `--aceptar`.
284
+ - Only `Datos Personales` is enabled in the interactive menu.
285
+ - Tests are offline with mocked HTML; they do not run a live ARCA sign-in.
286
+ - `logout` only removes the stored session; it does not close browser sessions that are already open.
287
+
288
+ ## Privacy and Packaging
289
+
290
+ The session file contains CUIT/CUIL, the person selection and authenticated browser state.
291
+ Treat it as a credential. The CLI never adds the tax password to this file. Session writes
292
+ replace the file atomically with mode `0600`; reading an older file repairs its permissions
293
+ and those of the session directory (`0700`) on macOS/Linux. Login and CLI errors redact
294
+ password values, including escaped browser call logs.
295
+
296
+ Console output, JSON exports and downloaded PDFs contain the requested personal tax data.
297
+ The default PDF names, copied session files, inspection directories, local environment
298
+ variants and package archives are ignored by Git. This does not replace checking any custom
299
+ export path before committing. All committed test fixtures use fictional identifiers and data.
300
+
301
+ `npm pack` runs a clean build through `prepack`. The package contains only compiled runtime
302
+ JavaScript and declarations, `package.json`, README and LICENSE. Tests, development tools,
303
+ environment files and source maps are excluded. Check the contents with:
304
+
305
+ ```bash
306
+ npm pack --dry-run
307
+ ```
308
+
309
+ ## License
310
+
311
+ [ISC](LICENSE).
@@ -0,0 +1,71 @@
1
+ import type { Page } from "playwright";
2
+ import type { DeductionDetailView, DeductionSummary } from "../types.js";
3
+ import { type SiradigRequestClient } from "./http.js";
4
+ export declare function readDeductions(page: Page, request?: SiradigRequestClient): Promise<DeductionSummary[]>;
5
+ export declare function parseDeductionsJson(data: unknown): DeductionSummary[] | null;
6
+ export declare function openDeductionsMenu(page: Page): Promise<void>;
7
+ export declare function listDeductions(page: Page): Promise<DeductionSummary[]>;
8
+ export declare function findDeductionById(page: Page, deductionId: string): Promise<(DeductionSummary & {
9
+ editUrl: string;
10
+ }) | null>;
11
+ export declare function findDeductionByTypeAndCuit(page: Page, type: string, cuit: string): Promise<(DeductionSummary & {
12
+ editUrl: string;
13
+ }) | null>;
14
+ export declare function findDeductionByTypeCuitAndMonth(page: Page, type: string, cuit: string, month: number): Promise<(DeductionSummary & {
15
+ editUrl: string;
16
+ }) | null>;
17
+ export declare function openDeductionDetail(page: Page, editUrl: string, deductionId: string): Promise<void>;
18
+ export declare function openDeductionDetailById(page: Page, deductionId: string): Promise<void>;
19
+ export declare function extractDeductionDetail(page: Page): Promise<DeductionDetailView>;
20
+ export declare function addDeductionMonthlyItem(page: Page, options: {
21
+ deductionType: string;
22
+ cuit: string;
23
+ month: number;
24
+ amount: string;
25
+ }): Promise<void>;
26
+ export declare function addDeductionMonthlyItemOnOpenPage(page: Page, options: {
27
+ month: number;
28
+ amount: string;
29
+ }): Promise<void>;
30
+ export declare function addDeductionReceiptItem(page: Page, options: {
31
+ deductionType: string;
32
+ cuit: string;
33
+ month: number;
34
+ date: string;
35
+ receiptType: string;
36
+ number: string;
37
+ amount: string;
38
+ reimbursedAmount?: string;
39
+ }): Promise<void>;
40
+ export declare function addDeductionReceiptItemOnOpenPage(page: Page, options: {
41
+ deductionType: string;
42
+ cuit: string;
43
+ month: number;
44
+ date: string;
45
+ receiptType: string;
46
+ number: string;
47
+ amount: string;
48
+ }): Promise<void>;
49
+ export declare function addMedicalExpenseReceiptItem(page: Page, options: {
50
+ cuit: string;
51
+ month: number;
52
+ date: string;
53
+ receiptType: string;
54
+ number: string;
55
+ amount: string;
56
+ reimbursedAmount: string;
57
+ }): Promise<void>;
58
+ export declare function removeMedicalExpenseReceiptItem(page: Page, options: {
59
+ cuit: string;
60
+ number: string;
61
+ }): Promise<void>;
62
+ export declare function addMedicalExpenseReceiptItemOnOpenPage(page: Page, options: {
63
+ cuit: string;
64
+ month: number;
65
+ date: string;
66
+ receiptType: string;
67
+ number: string;
68
+ amount: string;
69
+ reimbursedAmount: string;
70
+ }): Promise<void>;
71
+ export declare function removeReceiptByNumberOnOpenPage(page: Page, receiptNumber: string): Promise<boolean>;