@albertomarturelo/sii-core 0.9.0 → 0.11.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 (90) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/dist/adapters/fake/index.d.ts +20 -4
  3. package/dist/adapters/fake/index.d.ts.map +1 -1
  4. package/dist/adapters/fake/index.js +38 -4
  5. package/dist/adapters/fake/index.js.map +1 -1
  6. package/dist/adapters/node/cookie-jar.d.ts +35 -0
  7. package/dist/adapters/node/cookie-jar.d.ts.map +1 -0
  8. package/dist/adapters/node/cookie-jar.js +211 -0
  9. package/dist/adapters/node/cookie-jar.js.map +1 -0
  10. package/dist/adapters/node/http.d.ts +12 -0
  11. package/dist/adapters/node/http.d.ts.map +1 -0
  12. package/dist/adapters/node/http.js +262 -0
  13. package/dist/adapters/node/http.js.map +1 -0
  14. package/dist/adapters/node/portal.d.ts.map +1 -1
  15. package/dist/adapters/node/portal.js +18 -8
  16. package/dist/adapters/node/portal.js.map +1 -1
  17. package/dist/adapters/node/response.d.ts +12 -4
  18. package/dist/adapters/node/response.d.ts.map +1 -1
  19. package/dist/adapters/node/response.js +36 -8
  20. package/dist/adapters/node/response.js.map +1 -1
  21. package/dist/auth/auth.d.ts +55 -6
  22. package/dist/auth/auth.d.ts.map +1 -1
  23. package/dist/auth/auth.js +238 -56
  24. package/dist/auth/auth.js.map +1 -1
  25. package/dist/auth/datos-cntr.d.ts +23 -0
  26. package/dist/auth/datos-cntr.d.ts.map +1 -0
  27. package/dist/auth/datos-cntr.js +81 -0
  28. package/dist/auth/datos-cntr.js.map +1 -0
  29. package/dist/auth/index.d.ts +1 -0
  30. package/dist/auth/index.d.ts.map +1 -1
  31. package/dist/auth/login-block.d.ts +23 -0
  32. package/dist/auth/login-block.d.ts.map +1 -0
  33. package/dist/auth/login-block.js +53 -0
  34. package/dist/auth/login-block.js.map +1 -0
  35. package/dist/auth/login-error.d.ts +20 -3
  36. package/dist/auth/login-error.d.ts.map +1 -1
  37. package/dist/auth/login-error.js +20 -5
  38. package/dist/auth/login-error.js.map +1 -1
  39. package/dist/auth/session.d.ts +29 -2
  40. package/dist/auth/session.d.ts.map +1 -1
  41. package/dist/auth/session.js +35 -2
  42. package/dist/auth/session.js.map +1 -1
  43. package/dist/auth/www2-login.d.ts +28 -0
  44. package/dist/auth/www2-login.d.ts.map +1 -0
  45. package/dist/auth/www2-login.js +101 -0
  46. package/dist/auth/www2-login.js.map +1 -0
  47. package/dist/cli.d.ts +2 -2
  48. package/dist/cli.d.ts.map +1 -1
  49. package/dist/cli.js +4 -1
  50. package/dist/cli.js.map +1 -1
  51. package/dist/config/config.d.ts +21 -0
  52. package/dist/config/config.d.ts.map +1 -1
  53. package/dist/config/config.js +21 -0
  54. package/dist/config/config.js.map +1 -1
  55. package/dist/errors/errors.d.ts +59 -2
  56. package/dist/errors/errors.d.ts.map +1 -1
  57. package/dist/errors/errors.js +55 -2
  58. package/dist/errors/errors.js.map +1 -1
  59. package/dist/index.d.ts +3 -1
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +1 -0
  62. package/dist/index.js.map +1 -1
  63. package/dist/node.d.ts +7 -3
  64. package/dist/node.d.ts.map +1 -1
  65. package/dist/node.js +10 -4
  66. package/dist/node.js.map +1 -1
  67. package/dist/portal/carpeta-tributaria-regular.d.ts +30 -0
  68. package/dist/portal/carpeta-tributaria-regular.d.ts.map +1 -0
  69. package/dist/portal/carpeta-tributaria-regular.js +142 -0
  70. package/dist/portal/carpeta-tributaria-regular.js.map +1 -0
  71. package/dist/portal/www2-session.d.ts +13 -0
  72. package/dist/portal/www2-session.d.ts.map +1 -0
  73. package/dist/portal/www2-session.js +61 -0
  74. package/dist/portal/www2-session.js.map +1 -0
  75. package/dist/seams/index.d.ts +7 -0
  76. package/dist/seams/index.d.ts.map +1 -1
  77. package/dist/tasks/auth.d.ts +23 -6
  78. package/dist/tasks/auth.d.ts.map +1 -1
  79. package/dist/tasks/auth.js +20 -5
  80. package/dist/tasks/auth.js.map +1 -1
  81. package/dist/tasks/bte.d.ts.map +1 -1
  82. package/dist/tasks/bte.js +4 -2
  83. package/dist/tasks/bte.js.map +1 -1
  84. package/dist/tasks/carpeta.d.ts +9 -0
  85. package/dist/tasks/carpeta.d.ts.map +1 -0
  86. package/dist/tasks/carpeta.js +49 -0
  87. package/dist/tasks/carpeta.js.map +1 -0
  88. package/dist/tasks/dte.js +8 -8
  89. package/dist/tasks/dte.js.map +1 -1
  90. package/package.json +1 -1
@@ -0,0 +1,53 @@
1
+ // The rejection latch (ADR-028). After SII rejects a Clave, an unattended login must not
2
+ // try the same stale value again on the next cron tick: repeated failures lock the account
3
+ // (ADR-004). The latch is a local record, `~/.sii/login-blocked.json` through the store seam
4
+ // (0600 like every store file), holding NO secret — only which RUT, when, and SII's código.
5
+ import { LoginFailedError, LoginQueuedError } from '../errors/index.js';
6
+ import { WRONG_CLAVE_CODIGO } from './login-error.js';
7
+ const LOGIN_BLOCK_KEY = 'login-blocked';
8
+ async function readEntries(store) {
9
+ const file = await store.read(LOGIN_BLOCK_KEY);
10
+ return Array.isArray(file?.entries) ? file.entries : [];
11
+ }
12
+ async function writeEntries(store, entries) {
13
+ if (entries.length === 0)
14
+ await store.delete(LOGIN_BLOCK_KEY);
15
+ else
16
+ await store.write(LOGIN_BLOCK_KEY, { entries });
17
+ }
18
+ /** Every latched RUT — what `auth status` reports, so a caller sees the block BEFORE it
19
+ * decides to log in, instead of discovering it as a refusal. */
20
+ export async function listLoginBlocks(store) {
21
+ return readEntries(store);
22
+ }
23
+ export async function readLoginBlock(store, rut) {
24
+ return (await readEntries(store)).find((e) => e.rut === rut) ?? null;
25
+ }
26
+ /** Did SII actually judge the Clave? Only then may the latch trip. SII's error page is the
27
+ * one that prints a código (`parseSiiLoginErrorDetail`), so a código is the signal — not
28
+ * `reason === 'wrong-clave'` alone: the locked-account página has its own, still unobserved
29
+ * código (login-error.ts), and locking out a locked account is the safe direction. Queue-it,
30
+ * a WAF refusal, a timeout or a network error carry no código: SII never saw the Clave. */
31
+ export function siiJudgedClave(err) {
32
+ return err instanceof LoginFailedError && !(err instanceof LoginQueuedError) && !!err.codigo;
33
+ }
34
+ export async function tripLoginBlock(runtime, rut, codigo) {
35
+ const rest = (await readEntries(runtime.store)).filter((e) => e.rut !== rut);
36
+ await writeEntries(runtime.store, [
37
+ ...rest,
38
+ { rut, at: runtime.clock.now().toISOString(), codigo },
39
+ ]);
40
+ }
41
+ /** Lift the latch for one RUT, or for every RUT when none is given. Returns the RUTs lifted. */
42
+ export async function clearLoginBlock(store, rut) {
43
+ const entries = await readEntries(store);
44
+ const lifted = entries.filter((e) => rut === undefined || e.rut === rut).map((e) => e.rut);
45
+ if (lifted.length > 0) {
46
+ await writeEntries(store, entries.filter((e) => !lifted.includes(e.rut)));
47
+ }
48
+ return lifted;
49
+ }
50
+ export function reasonForCodigo(codigo) {
51
+ return codigo === WRONG_CLAVE_CODIGO ? 'wrong-clave' : 'unknown';
52
+ }
53
+ //# sourceMappingURL=login-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-block.js","sourceRoot":"","sources":["../../src/auth/login-block.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,25 @@
1
- /** Extract SII's verbatim login-error cause from the failed-login page body text.
1
+ import type { LoginFailureReason } from '../errors/index.js';
2
+ /** SII's message código for a wrong Clave Tributaria, observed 2026-06-28
3
+ * (docs/sii-contract/auth-login.md). It is the ONLY código classified as
4
+ * `'wrong-clave'`; the locked-account página has a DISTINCT código, not yet
5
+ * observed (triggering it risks a real lock, ADR-004/ADR-010), so it stays
6
+ * `'unknown'` until captured. */
7
+ export declare const WRONG_CLAVE_CODIGO = "01.01.203.500.720.20";
8
+ export interface SiiLoginErrorDetail {
9
+ /** `"<causa> (<código line>)"` verbatim, or `null` if the page shape changed. */
10
+ message: string | null;
11
+ /** The código SII printed (e.g. `01.01.203.500.720.20`), or `null` if none. */
12
+ codigo: string | null;
13
+ /** Classified from `codigo` — `'wrong-clave'` only for `WRONG_CLAVE_CODIGO`. */
14
+ reason: LoginFailureReason;
15
+ }
16
+ /** Parse SII's failed-login page body into {message, codigo, reason}.
2
17
  * Observed 2026-06-28 (docs/sii-contract/auth-login.md): the page renders the
3
18
  * human cause, then a line `El código de este mensaje es <código>`. The line
4
19
  * BEFORE the código line is the cause (e.g. "La Clave Tributaria ingresada no es
5
- * correcta…"). Returns `"<causa> (<código line>)"`, or `null` if the shape
6
- * changed (the caller falls back to a generic no-retry message). */
20
+ * correcta…"). A changed shape ⇒ `{message: null, codigo: null, reason: 'unknown'}`
21
+ * (the caller falls back to a generic no-retry message). */
22
+ export declare function parseSiiLoginErrorDetail(bodyText: string): SiiLoginErrorDetail;
23
+ /** Back-compat string view: SII's verbatim cause line, or `null` if the shape changed. */
7
24
  export declare function parseSiiLoginError(bodyText: string): string | null;
8
25
  //# sourceMappingURL=login-error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"login-error.d.ts","sourceRoot":"","sources":["../../src/auth/login-error.ts"],"names":[],"mappings":"AAIA;;;;;qEAKqE;AACrE,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOlE"}
1
+ {"version":3,"file":"login-error.d.ts","sourceRoot":"","sources":["../../src/auth/login-error.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D;;;;kCAIkC;AAClC,eAAO,MAAM,kBAAkB,yBAAyB,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gFAAgF;IAChF,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED;;;;;6DAK6D;AAC7D,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CAW9E;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAElE"}
@@ -1,18 +1,33 @@
1
1
  // Pure parser for SII's failed-login page (rendered on zeusr.sii.cl at
2
2
  // /cgi_AUT2000/CAutInicio.cgi). Kept DOM-free so it is unit-testable in Node;
3
3
  // the Playwright adapter passes it the page's `innerText` (adapters/node/portal.ts).
4
- /** Extract SII's verbatim login-error cause from the failed-login page body text.
4
+ /** SII's message código for a wrong Clave Tributaria, observed 2026-06-28
5
+ * (docs/sii-contract/auth-login.md). It is the ONLY código classified as
6
+ * `'wrong-clave'`; the locked-account página has a DISTINCT código, not yet
7
+ * observed (triggering it risks a real lock, ADR-004/ADR-010), so it stays
8
+ * `'unknown'` until captured. */
9
+ export const WRONG_CLAVE_CODIGO = '01.01.203.500.720.20';
10
+ /** Parse SII's failed-login page body into {message, codigo, reason}.
5
11
  * Observed 2026-06-28 (docs/sii-contract/auth-login.md): the page renders the
6
12
  * human cause, then a line `El código de este mensaje es <código>`. The line
7
13
  * BEFORE the código line is the cause (e.g. "La Clave Tributaria ingresada no es
8
- * correcta…"). Returns `"<causa> (<código line>)"`, or `null` if the shape
9
- * changed (the caller falls back to a generic no-retry message). */
10
- export function parseSiiLoginError(bodyText) {
14
+ * correcta…"). A changed shape ⇒ `{message: null, codigo: null, reason: 'unknown'}`
15
+ * (the caller falls back to a generic no-retry message). */
16
+ export function parseSiiLoginErrorDetail(bodyText) {
11
17
  const lines = bodyText
12
18
  .split('\n')
13
19
  .map((l) => l.trim())
14
20
  .filter(Boolean);
15
21
  const i = lines.findIndex((l) => /El c[oó]digo de este mensaje/i.test(l));
16
- return i > 0 ? `${lines[i - 1]} (${lines[i]})` : null;
22
+ if (i <= 0)
23
+ return { message: null, codigo: null, reason: 'unknown' };
24
+ const codigoLine = lines[i] ?? '';
25
+ const codigo = /El c[oó]digo de este mensaje es\s+([0-9][0-9.]*)/i.exec(codigoLine)?.[1] ?? null;
26
+ const reason = codigo === WRONG_CLAVE_CODIGO ? 'wrong-clave' : 'unknown';
27
+ return { message: `${lines[i - 1]} (${codigoLine})`, codigo, reason };
28
+ }
29
+ /** Back-compat string view: SII's verbatim cause line, or `null` if the shape changed. */
30
+ export function parseSiiLoginError(bodyText) {
31
+ return parseSiiLoginErrorDetail(bodyText).message;
17
32
  }
18
33
  //# sourceMappingURL=login-error.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login-error.js","sourceRoot":"","sources":["../../src/auth/login-error.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,8EAA8E;AAC9E,qFAAqF;AAErF;;;;;qEAKqE;AACrE,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,MAAM,KAAK,GAAG,QAAQ;SACnB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC"}
1
+ {"version":3,"file":"login-error.js","sourceRoot":"","sources":["../../src/auth/login-error.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,8EAA8E;AAC9E,qFAAqF;AAIrF;;;;kCAIkC;AAClC,MAAM,CAAC,MAAM,kBAAkB,GAAG,sBAAsB,CAAC;AAWzD;;;;;6DAK6D;AAC7D,MAAM,UAAU,wBAAwB,CAAC,QAAgB;IACvD,MAAM,KAAK,GAAG,QAAQ;SACnB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACtE,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,mDAAmD,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACjG,MAAM,MAAM,GAAuB,MAAM,KAAK,kBAAkB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7F,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACxE,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,wBAAwB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;AACpD,CAAC"}
@@ -1,14 +1,33 @@
1
- import type { KeyValueStore, PortalSession, Runtime } from '../seams/index.js';
1
+ import type { KeyValueStore, PortalDriver, PortalSession, Runtime } from '../seams/index.js';
2
+ /** The runtime's JS engine (Playwright), or an actionable error. The HTTP default `portal`
3
+ * cannot run SII's page JS (ADR-027); a surface that needs it (BTE list, MIPYME) asks for the
4
+ * `browser` engine, and the MCP's headed / www2 logins use it directly. */
5
+ export declare function requireBrowser(runtime: Runtime): PortalDriver;
6
+ /** The www2 APP-SESSION layer riding in the same cookies-only jar (ADR-026). Present only after
7
+ * `sii auth login --www2`; `expiresAt` is the `X-SII-STATE-CT` cookie's own expiry (observed
8
+ * ~100 min), null when the cookie carried none. Metadata only — the cookies themselves live in
9
+ * `cookies` like the classic ones. */
10
+ export interface StoredWww2Layer {
11
+ readonly savedAt: string;
12
+ readonly expiresAt: string | null;
13
+ }
2
14
  export interface StoredSession {
3
15
  /** Canonical session-principal RUT (read from the portal, not a credential). */
4
16
  readonly rut: string;
5
- /** Cookies-only storage state (opaque to the core). */
17
+ /** Cookies-only storage state (opaque to the core). Holds BOTH layers once `--www2` ran. */
6
18
  readonly cookies: unknown;
7
19
  readonly savedAt: string;
20
+ readonly www2?: StoredWww2Layer;
8
21
  }
9
22
  export declare function readSession(store: KeyValueStore): Promise<StoredSession | null>;
10
23
  export declare function writeSession(store: KeyValueStore, session: StoredSession): Promise<void>;
11
24
  export declare function deleteSession(store: KeyValueStore): Promise<void>;
25
+ /** Reject a representing operate pointer BEFORE opening a session — the guard every SESSION-KEYED
26
+ * surface (F29, BHE, Carpeta…) runs first (ADR-005). `error` builds the surface's own typed error
27
+ * from the formatted empresa RUT (already user-visible via `operate --list`, so safe to echo; the
28
+ * razón social is PII and is NOT passed). No operate state → resolves; `withSession` then raises
29
+ * NotAuthenticated. Single implementation: the third copy (carpeta) turned it into a helper. */
30
+ export declare function assertOperatingSelf(runtime: Runtime, error: (empresaFormatted: string) => Error): Promise<void>;
12
31
  export interface SessionContext {
13
32
  /** Canonical session-principal RUT (who is logged in). */
14
33
  readonly sessionRut: string;
@@ -27,5 +46,13 @@ export interface SessionContext {
27
46
  * retries after a SII block (CONVENTIONS). */
28
47
  export declare function withSession<T>(runtime: Runtime, fn: (session: PortalSession, ctx: SessionContext) => Promise<T>, options?: {
29
48
  rut?: string;
49
+ engine?: 'browser';
50
+ }): Promise<T>;
51
+ /** `withSession` pinned to the browser engine — for the surfaces that run SII's OWN page JS
52
+ * (BTE `list`'s inline maps, MIPYME's `validaFacEx`), ADR-027. Sugar so those call sites read
53
+ * intent-first and never need Chromium elsewhere. Raises `BrowserRequiredError` when the
54
+ * runtime carries no `browser` engine. */
55
+ export declare function withBrowserSession<T>(runtime: Runtime, fn: (session: PortalSession, ctx: SessionContext) => Promise<T>, options?: {
56
+ rut?: string;
30
57
  }): Promise<T>;
31
58
  //# sourceMappingURL=session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/auth/session.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAK/E,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAErF;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9F;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;mDAE+C;IAC/C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;+CAO+C;AAC/C,wBAAsB,WAAW,CAAC,CAAC,EACjC,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,EAC/D,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7B,OAAO,CAAC,CAAC,CAAC,CA4BZ"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/auth/session.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE7F;;4EAE4E;AAC5E,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAS7D;AAKD;;;uCAGuC;AACvC,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,CAAC;CACjC;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAErF;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9F;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED;;;;iGAIiG;AACjG,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,KAAK,GACzC,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;mDAE+C;IAC/C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;+CAO+C;AAC/C,wBAAsB,WAAW,CAAC,CAAC,EACjC,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,EAC/D,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAO,GACjD,OAAO,CAAC,CAAC,CAAC,CAgCZ;AAED;;;2CAG2C;AAC3C,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,EAC/D,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7B,OAAO,CAAC,CAAC,CAAC,CAEZ"}
@@ -1,5 +1,17 @@
1
- import { NotAuthenticatedError } from '../errors/index.js';
1
+ import { BrowserRequiredError, NotAuthenticatedError } from '../errors/index.js';
2
2
  import { readOperateState, resolveOperableTarget } from '../identity/index.js';
3
+ import { Rut } from '../rut/index.js';
4
+ /** The runtime's JS engine (Playwright), or an actionable error. The HTTP default `portal`
5
+ * cannot run SII's page JS (ADR-027); a surface that needs it (BTE list, MIPYME) asks for the
6
+ * `browser` engine, and the MCP's headed / www2 logins use it directly. */
7
+ export function requireBrowser(runtime) {
8
+ if (!runtime.browser) {
9
+ throw new BrowserRequiredError('Esta operación necesita el motor de navegador (Playwright), que este runtime no tiene ' +
10
+ 'configurado. En el CLI, las superficies que lo requieren (BTE list, factura MIPYME) ' +
11
+ 'necesitan `playwright` instalado; el login con navegador vive en el MCP (ADR-027).');
12
+ }
13
+ return runtime.browser;
14
+ }
3
15
  // Distinct KeyValueStore key (ADR-007) — never shares a file with `identity`'s 'operate'.
4
16
  const SESSION_KEY = 'session';
5
17
  export async function readSession(store) {
@@ -11,6 +23,17 @@ export async function writeSession(store, session) {
11
23
  export async function deleteSession(store) {
12
24
  await store.delete(SESSION_KEY);
13
25
  }
26
+ /** Reject a representing operate pointer BEFORE opening a session — the guard every SESSION-KEYED
27
+ * surface (F29, BHE, Carpeta…) runs first (ADR-005). `error` builds the surface's own typed error
28
+ * from the formatted empresa RUT (already user-visible via `operate --list`, so safe to echo; the
29
+ * razón social is PII and is NOT passed). No operate state → resolves; `withSession` then raises
30
+ * NotAuthenticated. Single implementation: the third copy (carpeta) turned it into a helper. */
31
+ export async function assertOperatingSelf(runtime, error) {
32
+ const op = await readOperateState(runtime.store);
33
+ if (op && op.operatingRut !== op.selfRut) {
34
+ throw error(Rut.parse(op.operatingRut).formatted);
35
+ }
36
+ }
14
37
  /** Acquire a live `PortalSession` from the stored cookies-only session and run `fn`
15
38
  * against it. This is how DOMAIN TASKS reach SII: they consume a session, they
16
39
  * NEVER mint one (only `login` mints — ADR-006, sii-py ADR-019). The operating/body
@@ -40,13 +63,23 @@ export async function withSession(runtime, fn, options = {}) {
40
63
  else {
41
64
  operatingRut = operateState?.operatingRut ?? stored.rut;
42
65
  }
66
+ // The default engine is the browser-free HTTP driver; a surface that runs SII's page JS
67
+ // asks for the `browser` engine, restored into the same cookies-only jar (ADR-027).
68
+ const driver = options.engine === 'browser' ? requireBrowser(runtime) : runtime.portal;
43
69
  let s = null;
44
70
  try {
45
- s = await runtime.portal.restore(stored.cookies);
71
+ s = await driver.restore(stored.cookies);
46
72
  return await fn(s, { sessionRut: stored.rut, operatingRut });
47
73
  }
48
74
  finally {
49
75
  await s?.close();
50
76
  }
51
77
  }
78
+ /** `withSession` pinned to the browser engine — for the surfaces that run SII's OWN page JS
79
+ * (BTE `list`'s inline maps, MIPYME's `validaFacEx`), ADR-027. Sugar so those call sites read
80
+ * intent-first and never need Chromium elsewhere. Raises `BrowserRequiredError` when the
81
+ * runtime carries no `browser` engine. */
82
+ export function withBrowserSession(runtime, fn, options = {}) {
83
+ return withSession(runtime, fn, { ...options, engine: 'browser' });
84
+ }
52
85
  //# sourceMappingURL=session.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/auth/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAG/E,0FAA0F;AAC1F,MAAM,WAAW,GAAG,SAAS,CAAC;AAU9B,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAoB;IACpD,OAAO,KAAK,CAAC,IAAI,CAAgB,WAAW,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAoB,EAAE,OAAsB;IAC7E,MAAM,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAoB;IACtD,MAAM,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAClC,CAAC;AAWD;;;;;;;+CAO+C;AAC/C,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAgB,EAChB,EAA+D,EAC/D,UAA4B,EAAE;IAE9B,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,qBAAqB,CAAC,0CAA0C,CAAC,CAAC;IAC9E,CAAC;IACD,2EAA2E;IAC3E,mFAAmF;IACnF,qFAAqF;IACrF,iFAAiF;IACjF,2EAA2E;IAC3E,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3D,IAAI,YAAoB,CAAC;IACzB,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,qBAAqB,CAAC,0CAA0C,CAAC,CAAC;QAC9E,CAAC;QACD,YAAY,GAAG,qBAAqB,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,YAAY,EAAE,YAAY,IAAI,MAAM,CAAC,GAAG,CAAC;IAC1D,CAAC;IAED,IAAI,CAAC,GAAyB,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,CAAC,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjD,OAAO,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;IAC/D,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/auth/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Www2Session } from '../portal/www2-session.js';
2
+ import type { PortalSession, Runtime } from '../seams/index.js';
3
+ /** Same budget as the classic headed login: a human has to read the chooser, type the Clave and
4
+ * pass the reCAPTCHA. */
5
+ export declare const WWW2_LOGIN_TIMEOUT_MS = 300000;
6
+ /** How often the app session is re-read while the user is at the OAuth page. Each read is one
7
+ * cheap GET the SPA itself issues on every route change (observed), paced via `Clock.sleep`. */
8
+ export declare const WWW2_POLL_MS = 2000;
9
+ /** The www2 app-session cookies all share this prefix (observed 2026-09-12): a literal
10
+ * `X-SII-STATE-TYPE` plus a state cookie whose suffix VARIES (`X-SII-STATE-CT` and
11
+ * `X-SII-STATE-CL` both seen — the letter is not stable), and every one carries the SAME
12
+ * expiry (~100 min). So the layer's expiry is read from ANY of them, not a fixed name. */
13
+ export declare const WWW2_STATE_COOKIE_PREFIX = "X-SII-STATE-";
14
+ /** Union of the classic jar (snapshotted BEFORE the www2 step) and the jar AFTER it: every classic
15
+ * cookie is kept, every www2 cookie is added, and on a same-identity collision the later (www2)
16
+ * value wins — a fresher load-balancer/analytics cookie, never a lost classic one. Falls back to
17
+ * the www2 state alone only when the classic one is not a cookie list at all. */
18
+ export declare function mergeStorageState(classic: unknown, www2: unknown): unknown;
19
+ /** ISO expiry of the www2 layer, read off any `X-SII-STATE-*` cookie (they share one expiry;
20
+ * Playwright carries `expires` as epoch SECONDS, `-1` = session cookie). Null when none is present
21
+ * or all are session-scoped. Takes the max, so a session-scoped `-TYPE` never masks a dated pair. */
22
+ export declare function www2ExpiresAt(state: unknown): string | null;
23
+ /** Drive the headed `session` (already past the classic login) to the www2 app page and wait for
24
+ * the user to complete SII's OAuth login there, polling the app-session read until it answers or
25
+ * the budget runs out. Resolves the session JSON; raises `LoginFailedError` on timeout. Any error
26
+ * other than "no app session yet" propagates — never retried (ADR-004). */
27
+ export declare function waitForWww2Session(runtime: Runtime, session: PortalSession, timeoutMs?: number): Promise<Www2Session>;
28
+ //# sourceMappingURL=www2-login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"www2-login.d.ts","sourceRoot":"","sources":["../../src/auth/www2-login.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEhE;0BAC0B;AAC1B,eAAO,MAAM,qBAAqB,SAAU,CAAC;AAC7C;iGACiG;AACjG,eAAO,MAAM,YAAY,OAAQ,CAAC;AAElC;;;2FAG2F;AAC3F,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AA8BvD;;;kFAGkF;AAClF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAS1E;AAED;;sGAEsG;AACtG,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAW3D;AAED;;;4EAG4E;AAC5E,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,aAAa,EACtB,SAAS,GAAE,MAA8B,GACxC,OAAO,CAAC,WAAW,CAAC,CAiBtB"}
@@ -0,0 +1,101 @@
1
+ // The www2 APP-SESSION step of `sii auth login --www2` (ADR-026): mint the second cookies-only
2
+ // layer `www2.sii.cl/app/*` needs, the ADR-006 way — the user types the Clave into SII's real
3
+ // OAuth page in the SAME headed browser the classic login used; we keep cookies only.
4
+ //
5
+ // Observed 2026-09-11/12 (#110, docs/sii-contract/auth-login.md § www2): the app page bounces an
6
+ // app-session-less browser to `/bifurcacion` (the chooser) → `/oauthsii-v1/` (Clave + reCAPTCHA
7
+ // Enterprise, hence NEVER automated — a human types) → `/app/session/create` → back to the app,
8
+ // now holding the httpOnly `.sii.cl` pair `X-SII-STATE-CT` + `X-SII-STATE-TYPE` (~100 min). The
9
+ // OAuth page WIPES the classic cookies from the browser context on mount, so the classic jar is
10
+ // snapshotted BEFORE this step and the www2 cookies are ADDED to it — never the reverse.
11
+ import { WWW2_APP_CARPETA } from '../config/index.js';
12
+ import { LoginFailedError, Www2SessionError } from '../errors/index.js';
13
+ import { readWww2Session } from '../portal/www2-session.js';
14
+ /** Same budget as the classic headed login: a human has to read the chooser, type the Clave and
15
+ * pass the reCAPTCHA. */
16
+ export const WWW2_LOGIN_TIMEOUT_MS = 300_000;
17
+ /** How often the app session is re-read while the user is at the OAuth page. Each read is one
18
+ * cheap GET the SPA itself issues on every route change (observed), paced via `Clock.sleep`. */
19
+ export const WWW2_POLL_MS = 2_000;
20
+ /** The www2 app-session cookies all share this prefix (observed 2026-09-12): a literal
21
+ * `X-SII-STATE-TYPE` plus a state cookie whose suffix VARIES (`X-SII-STATE-CT` and
22
+ * `X-SII-STATE-CL` both seen — the letter is not stable), and every one carries the SAME
23
+ * expiry (~100 min). So the layer's expiry is read from ANY of them, not a fixed name. */
24
+ export const WWW2_STATE_COOKIE_PREFIX = 'X-SII-STATE-';
25
+ const cookiesOf = (state) => {
26
+ if (state &&
27
+ typeof state === 'object' &&
28
+ Array.isArray(state.cookies)) {
29
+ return state.cookies;
30
+ }
31
+ return null;
32
+ };
33
+ // Identity of a cookie for the merge: name + domain + path (a scalar entry — the fakes use plain
34
+ // strings — keys by its own JSON so it survives the union untouched).
35
+ const keyOf = (c) => {
36
+ if (c && typeof c === 'object') {
37
+ const k = c;
38
+ return `${String(k.name)}|${String(k.domain)}|${String(k.path)}`;
39
+ }
40
+ return JSON.stringify(c);
41
+ };
42
+ /** Union of the classic jar (snapshotted BEFORE the www2 step) and the jar AFTER it: every classic
43
+ * cookie is kept, every www2 cookie is added, and on a same-identity collision the later (www2)
44
+ * value wins — a fresher load-balancer/analytics cookie, never a lost classic one. Falls back to
45
+ * the www2 state alone only when the classic one is not a cookie list at all. */
46
+ export function mergeStorageState(classic, www2) {
47
+ const a = cookiesOf(classic);
48
+ const b = cookiesOf(www2);
49
+ if (!a)
50
+ return www2;
51
+ if (!b)
52
+ return classic;
53
+ const merged = new Map();
54
+ for (const c of a)
55
+ merged.set(keyOf(c), c);
56
+ for (const c of b)
57
+ merged.set(keyOf(c), c);
58
+ return { ...www2, cookies: [...merged.values()] };
59
+ }
60
+ /** ISO expiry of the www2 layer, read off any `X-SII-STATE-*` cookie (they share one expiry;
61
+ * Playwright carries `expires` as epoch SECONDS, `-1` = session cookie). Null when none is present
62
+ * or all are session-scoped. Takes the max, so a session-scoped `-TYPE` never masks a dated pair. */
63
+ export function www2ExpiresAt(state) {
64
+ let best = 0;
65
+ for (const c of cookiesOf(state) ?? []) {
66
+ if (!c || typeof c !== 'object')
67
+ continue;
68
+ const k = c;
69
+ if (typeof k.name !== 'string' || !k.name.startsWith(WWW2_STATE_COOKIE_PREFIX))
70
+ continue;
71
+ if (typeof k.expires === 'number' && k.expires > best)
72
+ best = k.expires;
73
+ }
74
+ if (best <= 0)
75
+ return null;
76
+ const d = new Date(best * 1000);
77
+ return Number.isNaN(d.getTime()) ? null : d.toISOString();
78
+ }
79
+ /** Drive the headed `session` (already past the classic login) to the www2 app page and wait for
80
+ * the user to complete SII's OAuth login there, polling the app-session read until it answers or
81
+ * the budget runs out. Resolves the session JSON; raises `LoginFailedError` on timeout. Any error
82
+ * other than "no app session yet" propagates — never retried (ADR-004). */
83
+ export async function waitForWww2Session(runtime, session, timeoutMs = WWW2_LOGIN_TIMEOUT_MS) {
84
+ const start = runtime.clock.now().getTime();
85
+ await session.goto(WWW2_APP_CARPETA);
86
+ for (;;) {
87
+ try {
88
+ return await readWww2Session(session, WWW2_APP_CARPETA);
89
+ }
90
+ catch (e) {
91
+ if (!(e instanceof Www2SessionError))
92
+ throw e;
93
+ }
94
+ if (runtime.clock.now().getTime() - start >= timeoutMs) {
95
+ throw new LoginFailedError('Login www2 no completado (tiempo agotado en la página OAuth del SII). La sesión de ' +
96
+ 'Mi SII sí quedó guardada; reintenta `sii auth login --www2` para la capa www2.');
97
+ }
98
+ await runtime.clock.sleep(WWW2_POLL_MS);
99
+ }
100
+ }
101
+ //# sourceMappingURL=www2-login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"www2-login.js","sourceRoot":"","sources":["../../src/auth/www2-login.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { consoleLogin, keyringLogin } from './tasks/auth.js';
2
- export type { AuthLoginResult } from './tasks/auth.js';
1
+ export { consoleLogin, keyringLogin, suppliedClaveLogin, unblockLogin } from './tasks/auth.js';
2
+ export type { AuthLoginResult, LoginSource } from './tasks/auth.js';
3
3
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/F,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/cli.js CHANGED
@@ -4,5 +4,8 @@
4
4
  // takes a password (ADR-006). The terminal CLI imports this subpath instead.
5
5
  // `keyringLogin` joins it for the same reason: it READS a Clave (from the OS keyring),
6
6
  // so it must be unreachable from the MCP server (ADR-025).
7
- export { consoleLogin, keyringLogin } from './tasks/auth.js';
7
+ // `suppliedClaveLogin` takes a Clave the CLI read from a named env var or stdin, and
8
+ // `unblockLogin` lifts the rejection latch that guards it — a human's reset, never the
9
+ // model's (ADR-028).
10
+ export { consoleLogin, keyringLogin, suppliedClaveLogin, unblockLogin } from './tasks/auth.js';
8
11
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,oHAAoH;AACpH,qGAAqG;AACrG,gFAAgF;AAChF,6EAA6E;AAC7E,uFAAuF;AACvF,2DAA2D;AAC3D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,oHAAoH;AACpH,qGAAqG;AACrG,gFAAgF;AAChF,6EAA6E;AAC7E,uFAAuF;AACvF,2DAA2D;AAC3D,qFAAqF;AACrF,uFAAuF;AACvF,qBAAqB;AACrB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
@@ -10,6 +10,12 @@ export declare const HOSTS: {
10
10
  readonly portal: "https://www.sii.cl";
11
11
  /** SPA JSON facades (RCV / F29 / F22) live under this host. */
12
12
  readonly portalApi: "https://www4.sii.cl";
13
+ /** The newer SPA apps + their `/app/<name>-api/*` JSON facades — first the Carpeta
14
+ * Tributaria (`/carpetatributaria/…` SPA over `/app/cte-api-carpetatributaria/{rut}/…`).
15
+ * The `.sii.cl` session cookie SSO-carries, but every `cte-api` call answers 401 until
16
+ * the app's own `GET /app/session/status?originalUrl=…` warm-up ran (observed
17
+ * 2026-09-11, #110). (#109 / #110) */
18
+ readonly portalApp: "https://www2.sii.cl";
13
19
  /** Legacy BHE/BTE consulta CGIs (boletas de honorarios). HTML skeleton filled
14
20
  * client-side from inline JS maps; read via `PortalSession.goto`/`evaluate`, NOT
15
21
  * the SDI-JSON facade. The `.sii.cl` session cookie SSO-carries here (observed
@@ -42,6 +48,21 @@ export declare const LOGIN_HOST = "zeusr.sii.cl";
42
48
  export declare const LOGIN_URL: string;
43
49
  /** Full server-side logout URL (host + path). The close redirects OFF this path. */
44
50
  export declare const LOGOUT_URL: string;
51
+ /** The login form's POST target (`action=/cgi_AUT2000/CAutInicio.cgi`, observed 2026-06-28 /
52
+ * re-confirmed 2026-10-17). The HTTP credential login POSTs the five form fields here after a
53
+ * warm-up GET of the login page (ADR-027). */
54
+ export declare const LOGIN_POST_URL: string;
55
+ /** SII's Queue-it waiting-room host (`salaespera.sii.cl`): the peak-load queue SII drops users
56
+ * into on heavy days. An HTTP client cannot pass it, so a login redirected here raises
57
+ * `LoginQueuedError` — surfaced, never retried (observed in the browser jar, ADR-027). */
58
+ export declare const QUEUE_IT_HOST = "salaespera.sii.cl";
59
+ /** The www2 app page `sii auth login --www2` opens for the user to complete SII's OAuth login
60
+ * (`/bifurcacion` → `/oauthsii-v1/` → `/app/session/create` → back here), and the `Referer` /
61
+ * `originalUrl` the Carpeta SPA sends on its own calls. Observed 2026-09-11/12 (#110, ADR-026). */
62
+ export declare const WWW2_APP_CARPETA: string;
63
+ /** The www2 app-session close (the SPA's `$logout`: `/app/session/close?originalUrl=…`, from the
64
+ * session library `chunk-vendors.659f67b1.js`, observed 2026-09-11). Best-effort on logout. */
65
+ export declare const WWW2_SESSION_CLOSE_URL: string;
45
66
  /** The keyring "service" every entry of this tool lives under; the account (`username`
46
67
  * in keyring terms) is the RUT. Lives here — with the other environment constants —
47
68
  * because BOTH the pure `keyringLogin` task (for its error message) and the Node
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,KAAK;IAChB,2FAA2F;;IAE3F,+FAA+F;;IAE/F,8FAA8F;;IAE9F,gGAAgG;;;IAGhG,+DAA+D;;IAE/D;;;uFAGmF;;IAEnF;;;;;oFAKgF;;IAEhF;wEACoE;;IAEpE;;;;0BAIsB;;IAEtB;6FACyF;;;CAGjF,CAAC;AAEX,+EAA+E;AAC/E,eAAO,MAAM,UAAU,iBAAiB,CAAC;AAEzC,yCAAyC;AACzC,eAAO,MAAM,SAAS,QAAqC,CAAC;AAE5D,oFAAoF;AACpF,eAAO,MAAM,UAAU,QAAsC,CAAC;AAE9D;;;sDAGsD;AACtD,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC,MAAM,WAAW,QAAQ;IACvB,sEAAsE;IACtE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AAED,eAAO,MAAM,gBAAgB,EAAE,QAG9B,CAAC;AAEF,yFAAyF;AACzF,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEpD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,KAAK;IAChB,2FAA2F;;IAE3F,+FAA+F;;IAE/F,8FAA8F;;IAE9F,gGAAgG;;;IAGhG,+DAA+D;;IAE/D;;;;2CAIuC;;IAEvC;;;uFAGmF;;IAEnF;;;;;oFAKgF;;IAEhF;wEACoE;;IAEpE;;;;0BAIsB;;IAEtB;6FACyF;;;CAGjF,CAAC;AAEX,+EAA+E;AAC/E,eAAO,MAAM,UAAU,iBAAiB,CAAC;AAEzC,yCAAyC;AACzC,eAAO,MAAM,SAAS,QAAqC,CAAC;AAE5D,oFAAoF;AACpF,eAAO,MAAM,UAAU,QAAsC,CAAC;AAE9D;;+CAE+C;AAC/C,eAAO,MAAM,cAAc,QAA8C,CAAC;AAE1E;;2FAE2F;AAC3F,eAAO,MAAM,aAAa,sBAAsB,CAAC;AAEjD;;oGAEoG;AACpG,eAAO,MAAM,gBAAgB,QAA2D,CAAC;AAEzF;gGACgG;AAChG,eAAO,MAAM,sBAAsB,QAAyC,CAAC;AAE7E;;;sDAGsD;AACtD,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC,MAAM,WAAW,QAAQ;IACvB,sEAAsE;IACtE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AAED,eAAO,MAAM,gBAAgB,EAAE,QAG9B,CAAC;AAEF,yFAAyF;AACzF,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEpD"}
@@ -13,6 +13,12 @@ export const HOSTS = {
13
13
  portal: 'https://www.sii.cl',
14
14
  /** SPA JSON facades (RCV / F29 / F22) live under this host. */
15
15
  portalApi: 'https://www4.sii.cl',
16
+ /** The newer SPA apps + their `/app/<name>-api/*` JSON facades — first the Carpeta
17
+ * Tributaria (`/carpetatributaria/…` SPA over `/app/cte-api-carpetatributaria/{rut}/…`).
18
+ * The `.sii.cl` session cookie SSO-carries, but every `cte-api` call answers 401 until
19
+ * the app's own `GET /app/session/status?originalUrl=…` warm-up ran (observed
20
+ * 2026-09-11, #110). (#109 / #110) */
21
+ portalApp: 'https://www2.sii.cl',
16
22
  /** Legacy BHE/BTE consulta CGIs (boletas de honorarios). HTML skeleton filled
17
23
  * client-side from inline JS maps; read via `PortalSession.goto`/`evaluate`, NOT
18
24
  * the SDI-JSON facade. The `.sii.cl` session cookie SSO-carries here (observed
@@ -45,6 +51,21 @@ export const LOGIN_HOST = 'zeusr.sii.cl';
45
51
  export const LOGIN_URL = `${HOSTS.login}${HOSTS.loginPath}`;
46
52
  /** Full server-side logout URL (host + path). The close redirects OFF this path. */
47
53
  export const LOGOUT_URL = `${HOSTS.login}${HOSTS.logoutPath}`;
54
+ /** The login form's POST target (`action=/cgi_AUT2000/CAutInicio.cgi`, observed 2026-06-28 /
55
+ * re-confirmed 2026-10-17). The HTTP credential login POSTs the five form fields here after a
56
+ * warm-up GET of the login page (ADR-027). */
57
+ export const LOGIN_POST_URL = `${HOSTS.login}/cgi_AUT2000/CAutInicio.cgi`;
58
+ /** SII's Queue-it waiting-room host (`salaespera.sii.cl`): the peak-load queue SII drops users
59
+ * into on heavy days. An HTTP client cannot pass it, so a login redirected here raises
60
+ * `LoginQueuedError` — surfaced, never retried (observed in the browser jar, ADR-027). */
61
+ export const QUEUE_IT_HOST = 'salaespera.sii.cl';
62
+ /** The www2 app page `sii auth login --www2` opens for the user to complete SII's OAuth login
63
+ * (`/bifurcacion` → `/oauthsii-v1/` → `/app/session/create` → back here), and the `Referer` /
64
+ * `originalUrl` the Carpeta SPA sends on its own calls. Observed 2026-09-11/12 (#110, ADR-026). */
65
+ export const WWW2_APP_CARPETA = `${HOSTS.portalApp}/carpetatributaria/generarcteregular`;
66
+ /** The www2 app-session close (the SPA's `$logout`: `/app/session/close?originalUrl=…`, from the
67
+ * session library `chunk-vendors.659f67b1.js`, observed 2026-09-11). Best-effort on logout. */
68
+ export const WWW2_SESSION_CLOSE_URL = `${HOSTS.portalApp}/app/session/close`;
48
69
  /** The keyring "service" every entry of this tool lives under; the account (`username`
49
70
  * in keyring terms) is the RUT. Lives here — with the other environment constants —
50
71
  * because BOTH the pure `keyringLogin` task (for its error message) and the Node
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,gFAAgF;AAChF,6DAA6D;AAE7D,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,2FAA2F;IAC3F,KAAK,EAAE,sBAAsB;IAC7B,+FAA+F;IAC/F,SAAS,EAAE,mDAAmD;IAC9D,8FAA8F;IAC9F,UAAU,EAAE,6BAA6B;IACzC,gGAAgG;IAChG,KAAK,EAAE,6CAA6C;IACpD,MAAM,EAAE,oBAAoB;IAC5B,+DAA+D;IAC/D,SAAS,EAAE,qBAAqB;IAChC;;;uFAGmF;IACnF,MAAM,EAAE,4BAA4B;IACpC;;;;;oFAKgF;IAChF,OAAO,EAAE,uCAAuC;IAChD;wEACoE;IACpE,UAAU,EAAE,+BAA+B;IAC3C;;;;0BAIsB;IACtB,MAAM,EAAE,oCAAoC;IAC5C;6FACyF;IACzF,KAAK,EAAE,uBAAuB;IAC9B,UAAU,EAAE,sDAAsD;CAC1D,CAAC;AAEX,+EAA+E;AAC/E,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC;AAEzC,yCAAyC;AACzC,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;AAE5D,oFAAoF;AACpF,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC;AAE9D;;;sDAGsD;AACtD,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AASrC,MAAM,CAAC,MAAM,gBAAgB,GAAa;IACxC,YAAY,EAAE,CAAC;IACf,iBAAiB,EAAE,EAAE;CACtB,CAAC;AAEF,yFAAyF;AACzF,MAAM,UAAU,QAAQ,CAAC,WAAmB;IAC1C,OAAO,GAAG,SAAS,IAAI,WAAW,EAAE,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,gFAAgF;AAChF,6DAA6D;AAE7D,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,2FAA2F;IAC3F,KAAK,EAAE,sBAAsB;IAC7B,+FAA+F;IAC/F,SAAS,EAAE,mDAAmD;IAC9D,8FAA8F;IAC9F,UAAU,EAAE,6BAA6B;IACzC,gGAAgG;IAChG,KAAK,EAAE,6CAA6C;IACpD,MAAM,EAAE,oBAAoB;IAC5B,+DAA+D;IAC/D,SAAS,EAAE,qBAAqB;IAChC;;;;2CAIuC;IACvC,SAAS,EAAE,qBAAqB;IAChC;;;uFAGmF;IACnF,MAAM,EAAE,4BAA4B;IACpC;;;;;oFAKgF;IAChF,OAAO,EAAE,uCAAuC;IAChD;wEACoE;IACpE,UAAU,EAAE,+BAA+B;IAC3C;;;;0BAIsB;IACtB,MAAM,EAAE,oCAAoC;IAC5C;6FACyF;IACzF,KAAK,EAAE,uBAAuB;IAC9B,UAAU,EAAE,sDAAsD;CAC1D,CAAC;AAEX,+EAA+E;AAC/E,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC;AAEzC,yCAAyC;AACzC,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;AAE5D,oFAAoF;AACpF,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC;AAE9D;;+CAE+C;AAC/C,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,KAAK,CAAC,KAAK,6BAA6B,CAAC;AAE1E;;2FAE2F;AAC3F,MAAM,CAAC,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAEjD;;oGAEoG;AACpG,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,KAAK,CAAC,SAAS,sCAAsC,CAAC;AAEzF;gGACgG;AAChG,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,KAAK,CAAC,SAAS,oBAAoB,CAAC;AAE7E;;;sDAGsD;AACtD,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AASrC,MAAM,CAAC,MAAM,gBAAgB,GAAa;IACxC,YAAY,EAAE,CAAC;IACf,iBAAiB,EAAE,EAAE;CACtB,CAAC;AAEF,yFAAyF;AACzF,MAAM,UAAU,QAAQ,CAAC,WAAmB;IAC1C,OAAO,GAAG,SAAS,IAAI,WAAW,EAAE,CAAC;AACvC,CAAC"}