@redact-secret/core 0.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,122 @@
1
+ /**
2
+ * The Node.js adapter: the N-API native addon, normalized to the internal
3
+ * binding contract (`decision-define-runtime-bindings`).
4
+ *
5
+ * The package's `imports` map reaches this module only under the `node`
6
+ * condition, so a browser build never resolves it and never pulls in the
7
+ * `node:` module below.
8
+ *
9
+ * Node's own loading has nothing to await, so `initialize()` here is a fast
10
+ * idempotent no-op in the addon. It stays part of the contract regardless, so
11
+ * the usage model does not vary by runtime.
12
+ */
13
+ import { createRequire } from "node:module";
14
+ import { SecretScanError } from "../errors.js";
15
+ /**
16
+ * One `optionalDependencies` entry per `node-publish-targets`, published in
17
+ * lockstep with this package (`bindings/node/npm/<platform>/package.json`).
18
+ * `os`/`cpu`/`libc` on each of those manifests is what makes every
19
+ * non-matching entry optional in the literal npm sense: an install skips
20
+ * the ones that do not match instead of failing on them.
21
+ *
22
+ * `node-publish-targets` is six of the eight triples `napi.targets` builds
23
+ * and qualifies: npm ships glibc only
24
+ * (`decision-ship-first-release-artifact-set`), so the two musl triples have
25
+ * no entry here and no libc dimension below — there is nothing for one to
26
+ * select between. A musl host's `process.platform`/`process.arch` still
27
+ * matches the `linux` glibc entry, and each manifest's `libc` field is not
28
+ * reliably enforced by every npm version, so a musl install can still
29
+ * resolve and install the glibc package (`docs/qualification.md`).
30
+ * `loadAddon`'s `require` of a glibc-linked `.node` file then fails to load
31
+ * under a musl runtime, caught the same way a missing optional dependency
32
+ * on any platform is, reaching the same `INITIALIZATION_FAILED` an
33
+ * explicitly unsupported host gets. `scripts/check-artifact-matrix.py`
34
+ * requires this mapping, the six `bindings/node/npm/<platform>/package.json`
35
+ * manifests, and this package's own `optionalDependencies` to name exactly
36
+ * the same six packages.
37
+ */
38
+ const PLATFORM_PACKAGES = {
39
+ darwin: {
40
+ arm64: "@redact-secret/node-darwin-arm64",
41
+ x64: "@redact-secret/node-darwin-x64",
42
+ },
43
+ linux: {
44
+ arm64: "@redact-secret/node-linux-arm64-gnu",
45
+ x64: "@redact-secret/node-linux-x64-gnu",
46
+ },
47
+ win32: {
48
+ arm64: "@redact-secret/node-win32-arm64-msvc",
49
+ x64: "@redact-secret/node-win32-x64-msvc",
50
+ },
51
+ };
52
+ /**
53
+ * The addon package this host should have installed, or `undefined` on a
54
+ * platform/architecture this package ships no addon for at all — the
55
+ * runtime fallback that keeps an unsupported host's failure identical to a
56
+ * supported host whose optional dependency did not install: both reach
57
+ * `loadAddon`'s own `INITIALIZATION_FAILED`, never a raw `require` error.
58
+ *
59
+ * Exported so `scripts/qualify-node-addon.mjs` and
60
+ * `scripts/qualify-package-consumer.mjs` compute the same host-to-package
61
+ * mapping this module actually loads from, instead of restating it.
62
+ */
63
+ export function resolveAddonSpecifier() {
64
+ return PLATFORM_PACKAGES[process.platform]?.[process.arch];
65
+ }
66
+ function loadAddon() {
67
+ const specifier = resolveAddonSpecifier();
68
+ if (specifier === undefined) {
69
+ throw new SecretScanError("INITIALIZATION_FAILED");
70
+ }
71
+ const require = createRequire(import.meta.url);
72
+ let addon;
73
+ try {
74
+ addon = require(specifier);
75
+ }
76
+ catch {
77
+ // Not installed (an optional dependency npm skipped, or one that failed
78
+ // to install) and a corrupt addon both fail the same fixed way.
79
+ throw new SecretScanError("INITIALIZATION_FAILED");
80
+ }
81
+ for (const name of [
82
+ "version",
83
+ "initialize",
84
+ "scan",
85
+ "redact",
86
+ "scanAndRedact",
87
+ ]) {
88
+ if (typeof addon[name] !== "function") {
89
+ throw new SecretScanError("INITIALIZATION_FAILED");
90
+ }
91
+ }
92
+ return addon;
93
+ }
94
+ /**
95
+ * Builds the internal binding contract from an already-loaded addon.
96
+ *
97
+ * Exported so a test double can exercise this exact normalization —
98
+ * including the `createIncrementalSanitizer` fallback — without loading the
99
+ * real addon, the way `runtime/browser.ts`'s
100
+ * `createBindingFromWasmModule` does for the WebAssembly artifact.
101
+ */
102
+ export function createBindingFromAddon(addon) {
103
+ return {
104
+ version: () => addon.version(),
105
+ initialize: () => {
106
+ addon.initialize();
107
+ },
108
+ scan: (input, policy) => addon.scan(input, policy),
109
+ redact: (input, findings, formatter) => addon.redact(input, findings, formatter),
110
+ scanAndRedact: (input, policy, formatter) => {
111
+ const result = addon.scanAndRedact(input, policy, formatter);
112
+ return { text: result.redacted, findings: result.findings };
113
+ },
114
+ createIncrementalSanitizer: (options) => {
115
+ if (typeof addon.createIncrementalSanitizer !== "function") {
116
+ throw new SecretScanError("INCREMENTAL_UNAVAILABLE");
117
+ }
118
+ return addon.createIncrementalSanitizer(options);
119
+ },
120
+ };
121
+ }
122
+ export const loadNativeBinding = async () => createBindingFromAddon(loadAddon());
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The runtime-neutral half of the package: the initialization contract and
3
+ * the operations it gates.
4
+ *
5
+ * {@link createRedactSecretRuntime} takes the loader for one runtime and returns
6
+ * the public operations bound to it. `index.ts` supplies the loader the
7
+ * package's `imports` map selected; tests supply their own. Nothing here
8
+ * inspects the host, imports a `node:` module, or touches a global.
9
+ */
10
+ import { type NativeBindingLoader } from "./native.js";
11
+ import type { IncrementalSanitizer, IncrementalSanitizerOptions, RedactOptions, ScanAndRedactOptions, ScanOptions, ScanResult, SecretFinding } from "./types.js";
12
+ export interface RedactSecretRuntime {
13
+ initialize(): Promise<void>;
14
+ scan(input: string, options?: ScanOptions): readonly SecretFinding[];
15
+ redact(input: string, findings: readonly SecretFinding[], options?: RedactOptions): string;
16
+ scanAndRedact(input: string, options?: ScanAndRedactOptions): ScanResult;
17
+ createIncrementalSanitizer(options: IncrementalSanitizerOptions): IncrementalSanitizer;
18
+ }
19
+ /**
20
+ * Binds the public operations to one runtime's loader.
21
+ *
22
+ * `initialize` is the whole lifecycle contract: it may be awaited any number
23
+ * of times from any number of call sites and loads at most once, it verifies
24
+ * that the loaded artifact reports this package's version
25
+ * (`decision-release-bindings-in-lockstep`), and every synchronous operation
26
+ * below fails with `NOT_INITIALIZED` until exactly one call has succeeded. A
27
+ * failed attempt is not cached: a caller may retry.
28
+ */
29
+ export declare function createRedactSecretRuntime(loadNativeBinding: NativeBindingLoader): RedactSecretRuntime;
@@ -0,0 +1,256 @@
1
+ /**
2
+ * The runtime-neutral half of the package: the initialization contract and
3
+ * the operations it gates.
4
+ *
5
+ * {@link createRedactSecretRuntime} takes the loader for one runtime and returns
6
+ * the public operations bound to it. `index.ts` supplies the loader the
7
+ * package's `imports` map selected; tests supply their own. Nothing here
8
+ * inspects the host, imports a `node:` module, or touches a global.
9
+ */
10
+ import { SecretScanError, toSecretScanError, } from "./errors.js";
11
+ import { defaultPlaceholderFormatter } from "./formatters.js";
12
+ import { NATIVE_HANDLE, } from "./native.js";
13
+ import { VERSION } from "./version.js";
14
+ /** Freezes the five documented fields a policy callback is allowed to see. */
15
+ function toDetectedSecretFinding(finding) {
16
+ return Object.freeze({
17
+ id: finding.id,
18
+ type: finding.type,
19
+ detector: finding.detector,
20
+ confidence: finding.confidence,
21
+ start: finding.start,
22
+ end: finding.end,
23
+ });
24
+ }
25
+ /** Freezes the seven documented fields, preserving any binding handle. */
26
+ function toSecretFinding(finding) {
27
+ const published = {
28
+ id: finding.id,
29
+ type: finding.type,
30
+ detector: finding.detector,
31
+ confidence: finding.confidence,
32
+ action: finding.action,
33
+ start: finding.start,
34
+ end: finding.end,
35
+ };
36
+ const handle = finding[NATIVE_HANDLE];
37
+ if (handle !== undefined) {
38
+ Object.defineProperty(published, NATIVE_HANDLE, {
39
+ value: handle,
40
+ enumerable: false,
41
+ writable: false,
42
+ configurable: false,
43
+ });
44
+ }
45
+ return Object.freeze(published);
46
+ }
47
+ function toSecretFindings(findings) {
48
+ return Object.freeze(findings.map(toSecretFinding));
49
+ }
50
+ /**
51
+ * Re-presents a public finding to the binding that produced it, carrying the
52
+ * binding handle back across when the finding has one.
53
+ *
54
+ * The WebAssembly binding's `redact` accepts only the opaque findings its own
55
+ * `scan` returned; that adapter rejects a finding that arrives without one
56
+ * rather than reinterpreting it. The Node addon reads the plain fields.
57
+ */
58
+ function toNativeFinding(finding) {
59
+ const handle = finding[NATIVE_HANDLE];
60
+ if (handle === undefined)
61
+ return finding;
62
+ return { ...finding, [NATIVE_HANDLE]: handle };
63
+ }
64
+ /**
65
+ * Matches a JavaScript string containing a lone (unpaired) UTF-16 surrogate:
66
+ * a high surrogate not immediately followed by a low surrogate, or a low
67
+ * surrogate not immediately preceded by a high surrogate. Such a code unit
68
+ * has no UTF-8 representation, so it cannot cross into either binding's Rust
69
+ * `&str` (`errors.ts`'s `UNPAIRED_SURROGATE` documentation).
70
+ */
71
+ const LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
72
+ function requireString(value) {
73
+ if (typeof value !== "string")
74
+ throw new SecretScanError("INVALID_INPUT");
75
+ if (LONE_SURROGATE.test(value)) {
76
+ throw new SecretScanError("UNPAIRED_SURROGATE");
77
+ }
78
+ return value;
79
+ }
80
+ function toPolicyCallback(policy) {
81
+ if (policy === undefined)
82
+ return undefined;
83
+ if (typeof policy !== "object" || typeof policy.evaluate !== "function") {
84
+ throw new SecretScanError("INVALID_OPTIONS");
85
+ }
86
+ return (finding, context) => policy.evaluate(toDetectedSecretFinding(finding), context);
87
+ }
88
+ /**
89
+ * Routes the exported default formatter back to the binding's own built-in
90
+ * rather than calling across the boundary for every placeholder, so the
91
+ * default path stays exactly the core's.
92
+ */
93
+ function toFormatterCallback(formatter) {
94
+ if (formatter === undefined || formatter === defaultPlaceholderFormatter) {
95
+ return undefined;
96
+ }
97
+ if (typeof formatter !== "function") {
98
+ throw new SecretScanError("INVALID_OPTIONS");
99
+ }
100
+ return (finding, context) => formatter(toSecretFinding(finding), context);
101
+ }
102
+ function toNativeIncrementalOptions(options) {
103
+ if (typeof options !== "object" || options === null) {
104
+ throw new SecretScanError("INVALID_OPTIONS");
105
+ }
106
+ const { limits, policy, placeholderFormatter } = options;
107
+ if (typeof limits !== "object" || limits === null) {
108
+ throw new SecretScanError("INVALID_LIMITS");
109
+ }
110
+ const formatter = toFormatterCallback(placeholderFormatter);
111
+ if (policy !== undefined &&
112
+ (typeof policy !== "object" || typeof policy.evaluate !== "function")) {
113
+ throw new SecretScanError("INVALID_OPTIONS");
114
+ }
115
+ const policyCallback = policy === undefined
116
+ ? undefined
117
+ : (finding, context) => policy.evaluate(toDetectedSecretFinding(finding), context);
118
+ return {
119
+ limits: {
120
+ maxInputCodeUnits: limits.maxInputCodeUnits,
121
+ maxBufferedCodeUnits: limits.maxBufferedCodeUnits,
122
+ maxTokenCodeUnits: limits.maxTokenCodeUnits,
123
+ maxMultilineCodeUnits: limits.maxMultilineCodeUnits,
124
+ },
125
+ ...(policyCallback === undefined ? {} : { policy: policyCallback }),
126
+ ...(formatter === undefined ? {} : { formatter }),
127
+ };
128
+ }
129
+ /**
130
+ * Binds the public operations to one runtime's loader.
131
+ *
132
+ * `initialize` is the whole lifecycle contract: it may be awaited any number
133
+ * of times from any number of call sites and loads at most once, it verifies
134
+ * that the loaded artifact reports this package's version
135
+ * (`decision-release-bindings-in-lockstep`), and every synchronous operation
136
+ * below fails with `NOT_INITIALIZED` until exactly one call has succeeded. A
137
+ * failed attempt is not cached: a caller may retry.
138
+ */
139
+ export function createRedactSecretRuntime(loadNativeBinding) {
140
+ let binding;
141
+ let pending;
142
+ async function load() {
143
+ let loaded;
144
+ try {
145
+ loaded = await loadNativeBinding();
146
+ if (loaded.version() !== VERSION) {
147
+ throw new SecretScanError("INITIALIZATION_FAILED");
148
+ }
149
+ loaded.initialize();
150
+ }
151
+ catch (thrown) {
152
+ throw toSecretScanError(thrown, "INITIALIZATION_FAILED");
153
+ }
154
+ binding = loaded;
155
+ }
156
+ function initialize() {
157
+ if (binding !== undefined)
158
+ return Promise.resolve();
159
+ pending ??= load().finally(() => {
160
+ pending = undefined;
161
+ });
162
+ return pending;
163
+ }
164
+ function active() {
165
+ if (binding === undefined)
166
+ throw new SecretScanError("NOT_INITIALIZED");
167
+ return binding;
168
+ }
169
+ function scan(input, options) {
170
+ const native = active();
171
+ const text = requireString(input);
172
+ const policy = toPolicyCallback(options?.policy);
173
+ try {
174
+ return toSecretFindings(native.scan(text, policy));
175
+ }
176
+ catch (thrown) {
177
+ throw toSecretScanError(thrown, "DETECTOR_FAILURE");
178
+ }
179
+ }
180
+ function redact(input, findings, options) {
181
+ const native = active();
182
+ const text = requireString(input);
183
+ if (!Array.isArray(findings)) {
184
+ throw new SecretScanError("INVALID_FINDINGS");
185
+ }
186
+ const formatter = toFormatterCallback(options?.placeholderFormatter);
187
+ try {
188
+ return native.redact(text, findings.map(toNativeFinding), formatter);
189
+ }
190
+ catch (thrown) {
191
+ throw toSecretScanError(thrown, "INVALID_FINDINGS");
192
+ }
193
+ }
194
+ function scanAndRedact(input, options) {
195
+ const native = active();
196
+ const text = requireString(input);
197
+ const policy = toPolicyCallback(options?.policy);
198
+ const formatter = toFormatterCallback(options?.placeholderFormatter);
199
+ let result;
200
+ try {
201
+ result = native.scanAndRedact(text, policy, formatter);
202
+ }
203
+ catch (thrown) {
204
+ throw toSecretScanError(thrown, "DETECTOR_FAILURE");
205
+ }
206
+ return Object.freeze({
207
+ text: result.text,
208
+ findings: toSecretFindings(result.findings),
209
+ });
210
+ }
211
+ function createIncrementalSanitizer(options) {
212
+ const native = active();
213
+ let session;
214
+ try {
215
+ session = native.createIncrementalSanitizer(toNativeIncrementalOptions(options));
216
+ }
217
+ catch (thrown) {
218
+ throw toSecretScanError(thrown, "INVALID_LIMITS");
219
+ }
220
+ function run(operation, fallback) {
221
+ let result;
222
+ try {
223
+ result = operation();
224
+ }
225
+ catch (thrown) {
226
+ throw toSecretScanError(thrown, fallback);
227
+ }
228
+ return Object.freeze({
229
+ text: result.text,
230
+ findings: toSecretFindings(result.findings),
231
+ });
232
+ }
233
+ return Object.freeze({
234
+ get state() {
235
+ return session.state;
236
+ },
237
+ append: (chunk) => run(() => session.append(requireString(chunk)), "DETECTOR_FAILURE"),
238
+ finalize: () => run(() => session.finalize(), "DETECTOR_FAILURE"),
239
+ abort: () => {
240
+ try {
241
+ session.abort();
242
+ }
243
+ catch (thrown) {
244
+ throw toSecretScanError(thrown, "INVALID_STATE");
245
+ }
246
+ },
247
+ });
248
+ }
249
+ return {
250
+ initialize,
251
+ scan,
252
+ redact,
253
+ scanAndRedact,
254
+ createIncrementalSanitizer,
255
+ };
256
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The one runtime this package binds for the host it is running on.
3
+ *
4
+ * `index.ts` and both stream adapters import this module rather than each
5
+ * building their own runtime, so a single `await initialize()` covers the
6
+ * whole public surface no matter which subpath a caller reached first. ESM
7
+ * evaluates this module once, so `dist/index.js` and
8
+ * `dist/adapters/node-stream.js` share the same loaded binding.
9
+ *
10
+ * Nothing here is part of the published API: the package's `exports` map does
11
+ * not reach this module.
12
+ */
13
+ export declare const runtime: import("./runtime.js").RedactSecretRuntime;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The one runtime this package binds for the host it is running on.
3
+ *
4
+ * `index.ts` and both stream adapters import this module rather than each
5
+ * building their own runtime, so a single `await initialize()` covers the
6
+ * whole public surface no matter which subpath a caller reached first. ESM
7
+ * evaluates this module once, so `dist/index.js` and
8
+ * `dist/adapters/node-stream.js` share the same loaded binding.
9
+ *
10
+ * Nothing here is part of the published API: the package's `exports` map does
11
+ * not reach this module.
12
+ */
13
+ import { loadNativeBinding } from "#native";
14
+ import { createRedactSecretRuntime } from "./runtime.js";
15
+ export const runtime = createRedactSecretRuntime(loadNativeBinding);
@@ -0,0 +1,117 @@
1
+ /**
2
+ * The documented public type contract of `@redact-secret/core`.
3
+ *
4
+ * Every range in this file is a `[start, end)` pair of **UTF-16 code-unit**
5
+ * offsets into the JavaScript string that produced it, so `input.slice(start,
6
+ * end)` selects exactly the matched span (`decision-define-runtime-bindings`).
7
+ * The Rust core reports UTF-8 byte offsets; the Node and browser bindings
8
+ * convert them without changing the selected span.
9
+ *
10
+ * Custom detector callbacks are deliberately absent: every built-in detector
11
+ * runs in Rust, and the first stable extension surface is a policy and a
12
+ * placeholder formatter, both of which receive safe metadata only.
13
+ */
14
+ /** The string-index unit every public range in this package uses. */
15
+ export type RangeUnit = "utf16-code-units";
16
+ /** How specific a detector considers a match. */
17
+ export type SecretConfidence = "high" | "medium" | "low";
18
+ /** What a policy decided to do with a finding. */
19
+ export type SecretAction = "redact" | "block" | "warn" | "allow";
20
+ /**
21
+ * A finding before policy evaluation: the safe metadata a policy callback
22
+ * receives. It never carries the input or the matched value.
23
+ */
24
+ export interface DetectedSecretFinding {
25
+ /** Deterministic finding id (`finding-1`, `finding-2`, ...). */
26
+ readonly id: string;
27
+ /** Finding type, for example `"jwt"` or `"aws_access_key_id"`. */
28
+ readonly type: string;
29
+ /** Id of the detector that produced this finding. */
30
+ readonly detector: string;
31
+ readonly confidence: SecretConfidence;
32
+ /** Start offset, in UTF-16 code units. */
33
+ readonly start: number;
34
+ /** End offset (exclusive), in UTF-16 code units. */
35
+ readonly end: number;
36
+ }
37
+ /** A finding after policy evaluation: the shape {@link scan} returns. */
38
+ export interface SecretFinding extends DetectedSecretFinding {
39
+ readonly action: SecretAction;
40
+ }
41
+ /** Position information passed alongside a finding to a policy. */
42
+ export interface PolicyContext {
43
+ /** Zero-based position in the finalized detection list. */
44
+ readonly findingIndex: number;
45
+ /** Total number of finalized findings for the input. */
46
+ readonly findingCount: number;
47
+ }
48
+ /**
49
+ * A custom policy. It sees safe metadata only, never the input or a matched
50
+ * value. Omit it to use the built-in policy, which runs in Rust.
51
+ */
52
+ export interface SecretPolicy {
53
+ evaluate(finding: DetectedSecretFinding, context: PolicyContext): SecretAction;
54
+ }
55
+ /** Position information passed to a placeholder formatter. */
56
+ export interface PlaceholderContext {
57
+ /** One-based position among findings that are actually replaced. */
58
+ readonly placeholderIndex: number;
59
+ }
60
+ /**
61
+ * A custom placeholder formatter. It sees safe metadata only, and its result
62
+ * is validated: an empty, oversized, or matched-value-reproducing placeholder
63
+ * is rejected.
64
+ */
65
+ export type PlaceholderFormatter = (finding: SecretFinding, context: PlaceholderContext) => string;
66
+ export interface ScanOptions {
67
+ readonly policy?: SecretPolicy;
68
+ }
69
+ export interface RedactOptions {
70
+ readonly placeholderFormatter?: PlaceholderFormatter;
71
+ }
72
+ export interface ScanAndRedactOptions extends ScanOptions, RedactOptions {
73
+ }
74
+ /** Sanitized text alongside every finding that produced it. */
75
+ export interface ScanResult {
76
+ readonly text: string;
77
+ readonly findings: readonly SecretFinding[];
78
+ }
79
+ /** The terminally distinct lifecycle states of an incremental session. */
80
+ export type IncrementalSanitizerState = "accepting" | "finalized" | "aborted" | "failed";
81
+ /** Position information passed alongside a finding to an incremental policy. */
82
+ export interface IncrementalPolicyContext {
83
+ /** Zero-based position among findings finalized by this session. */
84
+ readonly findingIndex: number;
85
+ }
86
+ /** A custom policy for an incremental session. */
87
+ export interface IncrementalSecretPolicy {
88
+ evaluate(finding: DetectedSecretFinding, context: IncrementalPolicyContext): SecretAction;
89
+ }
90
+ /**
91
+ * Explicit, positive UTF-16 code-unit limits every incremental session
92
+ * requires. There are no environment-derived or silent defaults.
93
+ */
94
+ export interface IncrementalLimits {
95
+ readonly maxInputCodeUnits: number;
96
+ readonly maxBufferedCodeUnits: number;
97
+ readonly maxTokenCodeUnits: number;
98
+ readonly maxMultilineCodeUnits: number;
99
+ }
100
+ export interface IncrementalSanitizerOptions extends RedactOptions {
101
+ readonly limits: IncrementalLimits;
102
+ readonly policy?: IncrementalSecretPolicy;
103
+ }
104
+ /** Safe output and final findings produced by one session operation. */
105
+ export interface IncrementalSanitizerResult extends ScanResult {
106
+ }
107
+ /**
108
+ * A bounded incremental session. `append` and `finalize` return only text and
109
+ * findings whose detection window is closed; findings carry absolute UTF-16
110
+ * offsets into the logical whole-session input.
111
+ */
112
+ export interface IncrementalSanitizer {
113
+ readonly state: IncrementalSanitizerState;
114
+ append(chunk: string): IncrementalSanitizerResult;
115
+ finalize(): IncrementalSanitizerResult;
116
+ abort(): void;
117
+ }
package/dist/types.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The documented public type contract of `@redact-secret/core`.
3
+ *
4
+ * Every range in this file is a `[start, end)` pair of **UTF-16 code-unit**
5
+ * offsets into the JavaScript string that produced it, so `input.slice(start,
6
+ * end)` selects exactly the matched span (`decision-define-runtime-bindings`).
7
+ * The Rust core reports UTF-8 byte offsets; the Node and browser bindings
8
+ * convert them without changing the selected span.
9
+ *
10
+ * Custom detector callbacks are deliberately absent: every built-in detector
11
+ * runs in Rust, and the first stable extension surface is a policy and a
12
+ * placeholder formatter, both of which receive safe metadata only.
13
+ */
14
+ export {};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The shared product version.
3
+ *
4
+ * The Rust crate, the npm package, the Python package, and the CLI carry one
5
+ * SemVer version per release (`decision-release-bindings-in-lockstep`), so
6
+ * `initialize()` refuses a binding artifact that reports a different one.
7
+ */
8
+ export declare const VERSION = "0.1.0-beta.1";
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The shared product version.
3
+ *
4
+ * The Rust crate, the npm package, the Python package, and the CLI carry one
5
+ * SemVer version per release (`decision-release-bindings-in-lockstep`), so
6
+ * `initialize()` refuses a binding artifact that reports a different one.
7
+ */
8
+ export const VERSION = "0.1.0-beta.1";
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@redact-secret/core",
3
+ "description": "Deterministic secret detection and redaction for browser and server JavaScript/TypeScript applications.",
4
+ "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/redact-secret/redact-secret.git",
8
+ "directory": "packages/javascript"
9
+ },
10
+ "homepage": "https://github.com/redact-secret/redact-secret#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/redact-secret/redact-secret/issues"
13
+ },
14
+ "keywords": [
15
+ "secret-detection",
16
+ "redaction",
17
+ "security",
18
+ "browser",
19
+ "node"
20
+ ],
21
+ "type": "module",
22
+ "sideEffects": false,
23
+ "files": [
24
+ "dist",
25
+ "README.md",
26
+ "LICENSE"
27
+ ],
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js"
32
+ },
33
+ "./node-stream": {
34
+ "types": "./dist/adapters/node-stream.d.ts",
35
+ "import": "./dist/adapters/node-stream.js"
36
+ },
37
+ "./web-stream": {
38
+ "types": "./dist/adapters/web-stream.d.ts",
39
+ "import": "./dist/adapters/web-stream.js"
40
+ },
41
+ "./package.json": "./package.json"
42
+ },
43
+ "imports": {
44
+ "#native": {
45
+ "node": "./dist/runtime/node.js",
46
+ "browser": "./dist/runtime/browser.js",
47
+ "default": "./dist/runtime/browser.js"
48
+ }
49
+ },
50
+ "types": "./dist/index.d.ts",
51
+ "engines": {
52
+ "node": "20.x || 22.x || 24.x"
53
+ },
54
+ "version": "0.1.0-beta.1",
55
+ "dependencies": {
56
+ "@redact-secret/wasm": "0.1.0-beta.1"
57
+ },
58
+ "optionalDependencies": {
59
+ "@redact-secret/node-darwin-arm64": "0.1.0-beta.1",
60
+ "@redact-secret/node-darwin-x64": "0.1.0-beta.1",
61
+ "@redact-secret/node-linux-arm64-gnu": "0.1.0-beta.1",
62
+ "@redact-secret/node-linux-x64-gnu": "0.1.0-beta.1",
63
+ "@redact-secret/node-win32-arm64-msvc": "0.1.0-beta.1",
64
+ "@redact-secret/node-win32-x64-msvc": "0.1.0-beta.1"
65
+ }
66
+ }