@primafuture/systemd-tasks 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.
@@ -0,0 +1,323 @@
1
+ # Implementation decisions and evidence
2
+
3
+ ## Maintainer-approved platform amendment
4
+
5
+ During the published socket-fdx migration, the maintainer explicitly selected
6
+ **Node 24.13.0+, Linux x64, glibc 2.28+** as this version's supported runtime.
7
+ This decision supersedes the original broader Node 24+/Linux wording for platform
8
+ support only. The original `IMPLEMENTATION.md` and `specification.md` were used
9
+ unchanged during implementation and independent review, then removed at the
10
+ maintainer's request when preparing version 1.0.0. All other requirements, including systemd 257+,
11
+ cgroup v2, lifecycle guarantees, and T01–T18, remain applicable.
12
+
13
+ ## Feasibility checkpoint
14
+
15
+ The initial Node experiments ran on 2026-09-07 with Node 24.13.0, npm 11.16.0,
16
+ systemd 257.9-0ubuntu2.4, Linux 6.17.0-14-generic, and the existing user manager.
17
+ The manager reported `degraded`; it was reachable and the isolated task scenarios
18
+ worked. No manager configuration, linger, permissions, or existing service was changed.
19
+
20
+ Reproduction commands from the project directory:
21
+
22
+ ```sh
23
+ node scripts/probe.mjs
24
+ node scripts/feasibility.mjs
25
+ node scripts/recovery-probe.mjs
26
+ ```
27
+
28
+ Each experiment creates unique `pf-systemd-tasks-*` identities. Its cleanup is
29
+ restricted to those exact task/retention pairs. Generated output stays inside the
30
+ project. `feasibility.mjs` launches separate Node clients and observers and sends
31
+ SIGKILL to the client after creation or stop acceptance. This is actual Node/D-Bus
32
+ integration, not a `systemd-run` wrapper test.
33
+
34
+ Observed before implementing the public API:
35
+
36
+ | Scenario | Observation |
37
+ | --- | --- |
38
+ | Literal argv, cwd, environment | Empty arguments, spaces, Unicode, quotes, `$`, and `%` survived direct `ExecStartEx` with `no-env-expand`. |
39
+ | Unix FD and binary output | Bytes `00 ff 80 0a` survived; the caller's FD remained open after acceptance and could then be closed. |
40
+ | Client death with file output | A service finished and wrote output after its Node client was SIGKILLed; a fresh Node observer recovered the result. |
41
+ | Success and application failure | Exit 0 and 7 remained observable after client death, with raw `success` and `exit-code` respectively. |
42
+ | Execution failure | Missing executable produced status 203 without entering the active state; an application deliberately returning 203 did enter it. Missing cwd produced status 200 without entering active. |
43
+ | Signal and runtime deadline | SIGKILL produced raw `signal`; a TERM-resistant task reached SIGKILL through the manager's runtime/stop timers and produced raw `timeout`. |
44
+ | Accepted stop followed by client death | The manager completed escalation without the requesting client. |
45
+ | Main exit and descendant cleanup | A detached (`setsid`) TERM-resistant descendant was gone before completion; main exit 0 remained available even though cleanup escalation produced raw `timeout`. |
46
+ | Lost application reply | A client abandoned its start promise and was killed after submission; lookup recovered the run, and an explicit colliding start was rejected. This is loss at the application boundary; precise wire loss is covered separately by injected transport tests. |
47
+ | Release and replacement | Releasing the pair allowed collection; an explicitly authorized experiment reusing the name received a different InvocationID. |
48
+ | Retention initialization failure | A missing retention executable prevented execution of the user command. The task had no InvocationID and no main exit evidence. |
49
+
50
+ An inactive unit with a pending start job is **not** complete. The experiment caught
51
+ this race; completion must also inspect the job and cgroup state. `Result=timeout`
52
+ alone cannot identify a runtime deadline: it can also describe stop or descendant
53
+ cleanup escalation. The API must preserve these distinctions without inventing causes.
54
+
55
+ ## Retention mechanism
56
+
57
+ Create the task and auxiliary service in one `StartTransientUnit` request, using
58
+ job mode `fail`. The task has `Requires` and `After` dependencies on its uniquely
59
+ named retention service. The auxiliary service runs `/usr/bin/true` with
60
+ `Type=oneshot`, `RemainAfterExit=yes`, and `Before` referencing the task. Therefore
61
+ retention activation precedes task execution, and the active auxiliary service
62
+ keeps the task referenced after termination without a living helper process.
63
+
64
+ The task uses `Type=exec`, `ExitType=main`, `KillMode=control-group`, `Restart=no`,
65
+ and manager-owned stop/runtime timers. It does not use `RemainAfterExit` itself.
66
+ Release checks both identities and completion before removing retention. Failed
67
+ states must also be reset to permit garbage collection. Stop may replace pending
68
+ jobs to cancel a queued start; creation never uses replacement or restart.
69
+
70
+ This relies on the [systemd 257 dependency-based garbage collection contract](https://github.com/systemd/systemd/blob/v257/man/systemd.unit.xml)
71
+ and the [257 service lifecycle](https://github.com/systemd/systemd/blob/v257/src/core/service.c).
72
+ It does not provide persistence across manager restart or reboot, or protection
73
+ against another equally privileged process changing these units.
74
+
75
+ ## Transport and native installation
76
+
77
+ The current transport is `dbus-next` 0.10.2 (MIT) with the published
78
+ `@primafuture/socket-fdx` 1.0.0 (ISC), installed under the direct npm alias
79
+ `usocket`. Its root export provides the compatible `USocket` constructor. No
80
+ installed dependency files or global prototypes are patched.
81
+
82
+ The following records the superseded feasibility candidates, not the current
83
+ runtime dependencies.
84
+ The originally requested `usocket` 0.3.0 failed to build: its node-gyp 7.1.2 reported
85
+ `Completion callback never invoked!` with Node 24.13.0 and Python 3.13.7. Because
86
+ that dependency is optional upstream, an apparently successful npm installation
87
+ silently omitted FD support. Connection must explicitly reject that condition.
88
+
89
+ `usocket` 1.0.3 built and transmitted descriptors using NAN 2.25.0 and node-gyp
90
+ 12.4.0, with the host's Python 3.13.7, make, and C++ compiler. Python is a native
91
+ build prerequisite, not a runtime dependency of task execution. Version 1.1.0
92
+ also built, but its node-gyp 13 dependency declares a newer Node minimum than the
93
+ tested 24.13.0; it was not selected.
94
+
95
+ The build bundles the pinned JavaScript D-Bus implementation and its resolved
96
+ JavaScript dependencies, while leaving `usocket` as a pinned external runtime
97
+ dependency. This makes the selected native version effective in consumer projects:
98
+ npm overrides in a published dependency do not control the consumer's resolution.
99
+ The development override also selects xml2js 0.6.2 instead of the vulnerable older
100
+ release. Licensing notices accompany bundled dependencies. No D-Bus wire protocol
101
+ is implemented by this library.
102
+
103
+ The transport adapter must bound pending calls and explicitly destroy the native
104
+ socket at disconnect. It uses a small, documented set of pinned transport internals
105
+ for FD capability checks and abandoned-call cleanup. Upstream maintenance age,
106
+ native compatibility, and these internal hooks are maintenance risks. Connection
107
+ preflight awaits non-FD D-Bus replies before returning a usable client, so the
108
+ first FD-bearing request follows the daemon's completed Hello exchange.
109
+
110
+ The replacement ships a Linux x64/glibc 2.28+ prebuild and requires Node 24.13.0+.
111
+ It has no runtime dependencies or install hook. Its Node-API boundary also uses
112
+ libuv, so arbitrary future ABI compatibility is not assumed. This project's
113
+ consumer smoke installs with `--ignore-scripts` and no overrides, checks the actual
114
+ aliased package identity and loaded `.node` binary, and executes tasks using FDs.
115
+
116
+ ## Environment and execution evidence
117
+
118
+ Before submission, read the manager environment and place inherited names absent
119
+ from the explicit map in `UnsetEnvironment`. Do not change the manager environment.
120
+ Systemd still supplies its own execution metadata. The experiment observed
121
+ `MANAGERPID`, `INVOCATION_ID`, `SYSTEMD_EXEC_PID`, `MEMORY_PRESSURE_WATCH`, and
122
+ `MEMORY_PRESSURE_WRITE`. This is not a byte-for-byte promise for the whole environment.
123
+ Concurrent external changes to manager configuration are outside the isolation
124
+ guarantee and must be documented.
125
+
126
+ Retained active-entry timestamps under `Type=exec`, main-exit fields, and raw
127
+ systemd results form the execution evidence. Numeric status 203 alone is not an
128
+ execution-failure classifier. If the manager never executed the main process,
129
+ the absence of an invocation and exit evidence remains explicit.
130
+
131
+ ## Supported baseline
132
+
133
+ V1 requires Node 24.13.0+ on Linux x64 with glibc 2.28+,
134
+ a local user manager with systemd 257 or newer,
135
+ Unix FD negotiation, and a cgroup v2 hierarchy. Version 257 is a conservative
136
+ baseline for the experimentally verified mapping; older releases are not claimed.
137
+ Only the concrete versions recorded above have been exercised at this checkpoint.
138
+
139
+ ## Final API and packaged verification
140
+
141
+ The frozen format is version 1. Intents include the normalized specification and
142
+ its SHA-256 fingerprint; references omit the specification and bind local UID,
143
+ machine ID, boot ID, bus ID, manager bus owner, and both service InvocationIDs.
144
+ An unavailable ID is null, never a wildcard for a later invocation. Manager changes
145
+ invalidate the connection; there is no implicit reconnect. Equal-privilege external
146
+ unit replacement remains a read/check/mutate race because the systemd methods
147
+ accept a unit name rather than an InvocationID precondition.
148
+
149
+ The build bundles 16 JavaScript packages and generates full attribution from the
150
+ actual source map. The pinned `socket-fdx` alias remains external. Both conditional
151
+ declaration branches are tested with strict NodeNext TypeScript consumers.
152
+ Installation is performed with scripts disabled. The smoke consumer has its own manifest and
153
+ node_modules under a fresh `.artifacts/package-smoke-*` directory, separate from
154
+ `src`, and imports only the installed tarball. A test-only CommonJS resolver guard
155
+ rejects absolute resolutions outside that consumer to exclude ancestor packages
156
+ (including optional `debug`/`supports-color` probes). Runtime require-cache checks
157
+ also reject dependency leakage. This is dependency isolation within the authorized
158
+ workspace, not a container or a second physical host.
159
+
160
+ The runtime artifacts import without a native connection. The unsupported-platform
161
+ smoke uses an injected `process.platform` value; no macOS or Windows execution is
162
+ claimed. The native package has no transitive runtime dependencies. Native ABI,
163
+ upstream maintenance, and reliance on pinned dbus-next internals require continued
164
+ maintenance and fresh packaged verification when upgrading.
165
+
166
+ Reproduce the final checks with:
167
+
168
+ ```sh
169
+ npm run check
170
+ npm run test:integration
171
+ ```
172
+
173
+ The second command repeats the real lifecycle suite, including the crash matrix,
174
+ retention, immediate exits, and descriptor leak checks. The following table maps
175
+ all acceptance scenarios to concrete evidence. `unit/` and `integration/` paths
176
+ are relative to `__tests__` in the repository; those sources are not published.
177
+
178
+ | ID | Evidence | Boundary |
179
+ | --- | --- | --- |
180
+ | T01 | `integration/execution.test.ts`, `unit/validation.test.ts`: literal argv, cwd, explicit env, immutable serializable preparation | Real executable and local validation |
181
+ | T02 | `integration/execution.test.ts`: binary input/output, separate channels, 32 MiB direct file output; crash matrix exits 0 and 7 | Real FDs and bounded observed RSS; not an arbitrary-volume benchmark |
182
+ | T03 | `integration/execution.test.ts`, `unit/io.test.ts`, `integration/faults.test.ts`: missing exec/cwd, executable permissions, I/O failures, status 203 distinction | Real OS errors; explicit D-Bus permission rejection injected |
183
+ | T04 | `integration/execution.test.ts`, `unit/evidence.test.ts`: signal, runtime escalation, raw result classification | Real manager timers plus deterministic evidence classification |
184
+ | T05 | `integration/execution.test.ts`, `unit/evidence.test.ts`: setsid TERM-resistant descendant disappears before completion; unreadable/populated cleanup never reports complete | Real descendant/cgroup behavior; incomplete evidence injected |
185
+ | T06 | `integration/crash.test.ts`: submitting Node process SIGKILL, fresh Node observer, retained file output | Real processes, two rounds per retained outcome |
186
+ | T07 | `integration/crash.test.ts`, `unit/lifecycle.test.ts`: accepted stop followed by stopping-client SIGKILL; cancellation delivery stages | Real escalation; precise cancellation timing injected |
187
+ | T08 | `integration/crash.test.ts`, `integration/lifecycle.test.ts`: runtime deadline without client, local abort/timeout leaves task and other waiter alive | Real manager and concurrent clients |
188
+ | T09 | `integration/faults.test.ts`, `unit/lifecycle.test.ts`, `scripts/feasibility.mjs`: lost reply, late recovery, missing unit, auxiliary collision and initialization failure | Actual accepted task with reply loss injected at adapter boundary; real collisions/failure; absent-after-unknown simulated |
189
+ | T10 | `integration/crash.test.ts`: success, exit 7, exec failure, signal, timeout, stop retained until explicit release | Real client deaths and fresh observers; repeated matrix |
190
+ | T11 | `integration/lifecycle.test.ts`, `integration/faults.test.ts`, `unit/lifecycle.test.ts`, `unit/evidence.test.ts`: recreated name, stale IDs, collisions, manager mismatch, incomplete reference | Real replacement/collision; alternate manager identity injected |
191
+ | T12 | `integration/lifecycle.test.ts`, `unit/lifecycle.test.ts`: 25 FD-bearing tasks with multiple waiters, abort, snapshot race, pending job, actual overlapping stop/release and deferred stop acknowledgment/cancellation | Real repetition and overlapping calls plus deterministic event ordering |
192
+ | T13 | `integration/faults.test.ts`, `unit/lifecycle.test.ts`: lost reads/mutations, permission vs NoReply, disconnect with pending waits | Adapter failures injected around real calls and fake transport; no manager shutdown |
193
+ | T14 | `integration/execution.test.ts`, `integration/lifecycle.test.ts`, `integration/faults.test.ts`, `integration/pipes.test.ts`, `unit/io.test.ts`: borrowed ownership, repeated FD-bearing execution and manager rejection counts, partial-open leaks, descriptor cleanup after disconnect | Real descriptors, native transport, Linux /proc measurements |
194
+ | T15 | `integration/pipes.test.ts`, `integration/lifecycle.test.ts`, `unit/io.test.ts`: append/truncate, hard-link coalescing, error side effects, EPIPE and EOF | Real files, FIFO-backed Unix pipes, and execution failures |
195
+ | T16 | `integration/lifecycle.test.ts`, `integration/crash.test.ts`, `unit/lifecycle.test.ts`: refuse live release, repeat release, preserve logs, independent total deadline, preserve reset/stop acknowledgment across timeout | Real retention and deterministic delayed observations |
196
+ | T17 | `unit/validation.test.ts`, `unit/environment.test.ts`, `scripts/smoke.ts`: invalid inputs, retention prerequisites, native architecture/libc rejection, simulated unsupported platform | Pure validation, isolated filesystem/native-loader faults through public connect, and installed import/connect check |
197
+ | T18 | `scripts/smoke.ts`: npm tarball install without scripts or overrides, published alias/native binary identity, ESM/CJS binary execution and release, .mts/.cts consumer types, artifact allowlist | Real installed artifact with ancestor-module isolation |
198
+
199
+ The runnable examples also exercise basic execution, fsynced intent before start,
200
+ a separate recovery process, fsynced result before release, local wait timeout,
201
+ manager runtime timeout, and explicit stop escalation. Their task IDs and output
202
+ records are saved under `.artifacts/examples`.
203
+
204
+ ## Explicit limitations of the evidence
205
+
206
+ Only Node 24.13.0 on Linux x86-64 and systemd 257.9 were run. Other Node minors,
207
+ architectures, distributions, kernel/controller combinations, newer systemd,
208
+ containers, restricted buses, and alternative native build toolchains are unverified.
209
+ The suite does not deliberately reboot the machine, stop/restart the user's manager,
210
+ change its environment, change linger, or change access policy. Manager restart,
211
+ bus loss, exact lost replies, and permission categories are represented by injected
212
+ boundaries where indicated above. Retention across actual manager shutdown is not
213
+ part of the contract. Cgroup escape by privileged code and hostile external changes
214
+ to owned units or I/O paths are outside the guarantee.
215
+
216
+ ## Acceptance result — 2026-09-07
217
+
218
+ All T01–T18 scenarios above passed within their stated evidence boundaries.
219
+ `npm run check` completed with 28 unit tests and 30 real integration tests passing,
220
+ zero skipped tests, a successful dual-format build, and all packaged runtime/type
221
+ smoke checks passing. A separate repeat of the integration suite passed all 30 tests
222
+ again. All four runnable example entrypoints completed successfully. After cleanup,
223
+ no `pf-systemd-tasks-*` units remained loaded in the user manager. The complete
224
+ locked dependency audit reported zero known vulnerabilities at verification time;
225
+ that is a dated registry result, not a guarantee of absence of vulnerabilities.
226
+
227
+ ## Independent review follow-up
228
+
229
+ The fresh review `2026-09-07_09-34-45` requested changes despite the passing baseline
230
+ suite. The original acceptance result above describes that baseline, not final
231
+ review approval. Two issues were confirmed:
232
+
233
+ - Connection preflight did not verify its fixed retention executable. `connect()`
234
+ now checks that `/usr/bin/true` resolves to a regular file with execute access,
235
+ reporting `UNSUPPORTED_ENVIRONMENT` before opening the bus. Three isolated
236
+ filesystem-fault tests exercise missing, non-regular, and non-executable cases
237
+ through the public `connect()` API without changing the host executable.
238
+ - Upstream `usocket@1.0.3` loses its FD array after a zero-byte native write. A
239
+ deterministic reproduction with two queued messages confirmed the missing FDs
240
+ on repeated drain attempts. The native loop also retains `msghdr.msg_control`
241
+ after clearing its local FD vector, permitting duplicate control payloads if a
242
+ single native call performs multiple successful partial sends.
243
+
244
+ The upstream dependency is now replaced by the independently implemented,
245
+ published `@primafuture/socket-fdx@1.0.0`. Its shipped
246
+ `docs/architecture-and-evidence.md` records F04/F05 native regressions: repeated
247
+ EAGAIN preserves descriptors, positive partial sends deliver them once, and an
248
+ independent receiver detects deliberately broken ancillary reuse as a negative
249
+ control. These are the dependency's recorded evidence, not tests rerun by this
250
+ consumer. This project verifies the published adapter through its own real systemd
251
+ integration and installed-package checks. The earlier patch draft is historical
252
+ only; no vendored patch or node_modules mutation is used.
253
+
254
+ The unused internal transport-version field was removed. Test callback comments
255
+ now describe their fixture boundary or the reason for an assertion, rather than
256
+ repeating the adjacent test title.
257
+
258
+ ## Published socket-fdx migration verification
259
+
260
+ The initial migration used registry package `@primafuture/socket-fdx@0.1.0-rc.0` with integrity
261
+ `sha512-9BjkqES7Jx/SQvk8Gzpj0BRcKhJPh0kQHNi9SsAPr7vM3LuVIH8hsYLcHQihxRExi+AEQrM07buq0lWn4TNVQA==`.
262
+ `npm ls usocket --all` resolves both the direct runtime dependency and development
263
+ dbus-next dependency to that single alias. The old NAN/node-gyp runtime dependency
264
+ closure is removed. The package remains external to the D-Bus JavaScript bundle.
265
+
266
+ `npm run check` passed 31 unit tests and 30 integration tests, followed by the
267
+ dual-format build and installed runtime/type smoke. A preceding separate integration
268
+ run also passed all 30 tests. Consumer installation used no overrides and disabled
269
+ install scripts; both module formats loaded the shipped socket-fdx native binary
270
+ and completed real binary FD output and release. The production dependency audit
271
+ reported zero known vulnerabilities. These results use the host environment
272
+ recorded above; the dependency's wider build matrix is not a downstream verification
273
+ claim for this project. Independent review is a separate gate from these checks.
274
+
275
+ The continuation review identified native environment error misclassification and
276
+ gaps in T12/T14 coverage. Native platform, ABI, and missing-binary codes now map to
277
+ `UNSUPPORTED_ENVIRONMENT`; public connection tests inject architecture and libc
278
+ capabilities without modifying the host. Two deferred-reply tests overlap stop
279
+ and release through completion and cancellation, and a real manager test overlaps
280
+ stop-with-wait and release. The 25-iteration loop now sends real output descriptors
281
+ and checks output plus per-iteration FD counts, including execution failures.
282
+ Eight real FD-bearing requests rejected by the manager also return to the original
283
+ FD count; disconnect checks confirm release of each connection's bus socket.
284
+ The revised `npm run check` passed 36 unit tests, 32 integration tests, both builds,
285
+ and all isolated package smoke checks, with no skipped tests.
286
+
287
+ The maintainer then requested the stable published `@primafuture/socket-fdx@1.0.0`.
288
+ The direct alias and installed-artifact identity assertion now pin that version;
289
+ its registry integrity is
290
+ `sha512-ASACXfVCDTUV2UQYh/mjTJ0HEbFjEZYkmZSV9HxMJ1YGmWVRcflwNlS2q83ucWypSzDIfG+HgbE2pxzU6XI+fA==`.
291
+ The installed native binary and both JavaScript runtime entrypoints have identical
292
+ SHA-256 hashes to the reviewed release candidate. The native SHA-256 is
293
+ `9ca53cde1620155c96e91a836f450ee43a6d8dcb339050c39107c5a87ccd7ae1`.
294
+ Both development and runtime dependency branches resolve to the stable alias.
295
+ The full aggregate check was rerun against 1.0.0 and passed the same 36 unit and
296
+ 32 integration tests, dual-format build, and all installed-artifact smoke checks.
297
+ The full locked dependency audit reported zero known vulnerabilities at that check.
298
+
299
+ A subsequent independent review found two additional defects. Release no longer
300
+ reuses a single-request transport budget for the entire multi-request sequence.
301
+ Its optional `ReleaseOptions` provide an independent total timeout (5000 ms by
302
+ default) and abort signal. Acknowledged reset and stop mutations retain accepted
303
+ delivery evidence if later observation times out; explicit absence remains a no-op.
304
+ Tests exercise individually timely reads whose sum exceeds the transport budget,
305
+ timeouts after reset/stop acknowledgment, and pre-submission cancellation.
306
+
307
+ Diagnostics now consume returned promises and thenables without awaiting them.
308
+ A separate child process under `--unhandled-rejections=strict` verifies delayed
309
+ sink rejection, rejecting thenables, and a never-settling observer, while accepted
310
+ task submission and disconnect still complete and no global rejection escapes.
311
+ The aggregate check after these fixes passed 41 unit tests, 32 real integration
312
+ tests, type checking, both distribution formats, and the isolated package smoke
313
+ with `ReleaseOptions` checked through both declaration branches.
314
+
315
+ Mixed release outcomes now retain a separate `acceptedCleanupMutations` count.
316
+ A later rejected/not-submitted step cannot overwrite earlier confirmed effects as
317
+ though the entire release were rejected. Later unknown delivery remains unknown,
318
+ while the count preserves preceding acknowledgments. Nine deterministic cases
319
+ cover rejection, non-submission, and uncertain delivery at each of the main reset,
320
+ retention reset, and retention stop boundaries. The unused raw object-path field
321
+ was removed; transport paths remain local to the D-Bus request that needs them.
322
+ The aggregate check passed 50 unit tests, 32 real integration tests, both builds,
323
+ and installed runtime/type verification including partial-cleanup error metadata.
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@primafuture/systemd-tasks",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "One-shot process tasks owned by the systemd user manager.",
6
+ "author": "PrimaFuture.cz s.r.o. <dev@primafuture.cz>",
7
+ "license": "ISC",
8
+ "engines": {
9
+ "node": ">=24.13.0"
10
+ },
11
+ "dependencies": {
12
+ "usocket": "npm:@primafuture/socket-fdx@1.0.0"
13
+ },
14
+ "overrides": {
15
+ "dbus-next": {
16
+ "usocket": "$usocket",
17
+ "xml2js": "0.6.2"
18
+ }
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "24.13.3",
22
+ "tsup": "8.5.0",
23
+ "tsx": "4.20.6",
24
+ "typescript": "5.9.3",
25
+ "dbus-next": "0.10.2"
26
+ },
27
+ "sideEffects": false,
28
+ "main": "./dist/index.cjs",
29
+ "module": "./dist/index.mjs",
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "import": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.mjs"
36
+ },
37
+ "require": {
38
+ "types": "./dist/index.d.cts",
39
+ "default": "./dist/index.cjs"
40
+ }
41
+ }
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "docs",
46
+ "README.md",
47
+ "CHANGELOG.md",
48
+ "LICENSE",
49
+ "THIRD_PARTY_NOTICES.md"
50
+ ],
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "scripts": {
55
+ "build": "tsup && tsx scripts/licenses.ts",
56
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.dev.json --noEmit",
57
+ "test": "node --import tsx --test --test-timeout=15000 __tests__/unit/*.test.ts",
58
+ "test:integration": "node --import tsx --test --test-concurrency=1 __tests__/integration/*.test.ts",
59
+ "smoke": "tsx scripts/smoke.ts",
60
+ "check": "npm run typecheck && npm test && npm run test:integration && npm run build && npm run smoke",
61
+ "prepublishOnly": "npm run check"
62
+ }
63
+ }