# @db3.ai/pure

> Small portable helpers for ordinary application data. They do not create an App or replace validation and authorization.

- Package: `@db3.ai/pure`
- Canonical page: [https://db3.ai/docs/package-pure](https://db3.ai/docs/package-pure)
- Markdown: [https://db3.ai/docs/package-pure.md](https://db3.ai/docs/package-pure.md)
- Framework source of truth: `packages/pure/README.md`

<a id="setup"></a>

## Install and copy the small example

Use Installation’s preview tarballs and development tools. App already depends on Pure, but a utility-only application can install just the supplied Pure tarball. After publication the package name is `@db3.ai/pure`.

- [Installation](https://db3.ai/docs/installation.md)

### Copy the shipped utility lab

```bash
mkdir -p examples
cp -R node_modules/@db3.ai/pure/examples/. examples/
```

<a id="run"></a>

## Normalize a tag selection

Run the copied example. Expect tags `Client` and `Internal`, `invalidRejected: true`, then recovery with `Internal`. Exact duplicates and whitespace/case variants collapse without sorting away the original selection order.

### Run the example

```bash
npx tsx examples/runNoteTags.ts
```

<a id="use"></a>

## Check the result before saving

`selectedStrings()` reports unknown entries in `invalid` but also retains them in `values`. This wrapper rejects invalid selections before a caller can persist them. Helpers expose mechanics; your feature decides whether unknown input is an error.

The HTTP boundary must still check that input is an array of strings. Normalization is not authorization, Unicode identity policy, HTML sanitization or a SQL escape mechanism.

### examples/selectNoteTags.ts

```typescript
import { selectedStrings, uniqueNormalizedStrings } from '@db3.ai/pure/collections';

/**
 * Validates tag selection against application-owned options before accepting it.
 *
 * selectedStrings() reports unknown values but retains them in its values array.
 * The application must reject invalid entries before persisting the selection.
 * @param selected - Raw string options already type-checked at the request boundary.
 * @returns Normalized, allowed tags with stable first-occurrence ordering.
 */
export function selectNoteTags(selected: readonly string[]): string[] {
	const options = uniqueNormalizedStrings([' Client ', 'Internal', 'client']);
	const result = selectedStrings(selected, options);
	if (result.invalid.length > 0) throw new Error('Choose a supported note tag.');
	return result.values;
}
```

<a id="testing"></a>

## Copy and run the test

Save the exact test as `tests/noteTags.test.ts`. Its relative import resolves the copied `examples/selectNoteTags.ts`. Change the allowed options and retain the rejected-value and recovery cases.

### tests/noteTags.test.ts

```typescript
import { expect, it } from 'vitest';
import { selectNoteTags } from '../examples/selectNoteTags';

it('normalizes allowed tags but rejects unknown selections before recovery', () => {
	expect(selectNoteTags([' client ', 'CLIENT', ' internal '])).toEqual(['Client', 'Internal']);
	expect(() => selectNoteTags(['Administrator'])).toThrow('supported note tag');
	expect(selectNoteTags(['Internal'])).toEqual(['Internal']);
	expect(selectNoteTags([])).toEqual([]);
});
```

<a id="run-tests"></a>

## Check the consumer

These commands run from your app root. No framework checkout or backend process is needed.

### Test and compile

```bash
npx vitest run tests/noteTags.test.ts
npx tsc --noEmit --target ES2022 --module ESNext --moduleResolution Bundler --types node --skipLibCheck examples/*.ts
```

<a id="reference"></a>

## Full public utility declarations

The sections below are generated from every typed Pure export in the staged package. They cover strings, collections, dates, records, errors, HTTP/auth/AI value helpers, URLs and ULIDs. The `/ai` helpers are portable value handling, not a provider SDK or agent runtime.

The tag scenario tests one common task. Other utility signatures are reference coverage, not evidence of a complete browser matrix. Some helpers return an error/null while others throw; check the return type and function comment. URL normalization is not a remote-fetch allowlist.

<a id="pure-root"></a>

## @db3.ai/pure

### @db3.ai/pure

```typescript
export * from '@db3.ai/pure/ai';
export * from '@db3.ai/pure/auth';
export * from '@db3.ai/pure/collections';
export * from '@db3.ai/pure/dates';
export * from '@db3.ai/pure/errors';
export * from '@db3.ai/pure/http';
export * from '@db3.ai/pure/records';
export * from '@db3.ai/pure/strings';
export * from '@db3.ai/pure/ulid';
export * from '@db3.ai/pure/urls';
```

<a id="pure-ai"></a>

## @db3.ai/pure/ai

### @db3.ai/pure/ai

````typescript
import { truncateText } from '@db3.ai/pure/strings';
export interface TextResponsePayload {
    output_text?: unknown;
    output?: unknown;
    error?: {
        message?: unknown;
    };
}
/**
 * Formats unique strings as a Markdown unordered-list block for prompt input.
 *
 * @example
 * ```ts
 * stringListPromptBlock('Audiences', ['Founders', 'Founders']);
 * // 'Audiences:\\n- Founders'
 * ```
 */
export declare function stringListPromptBlock(title: string, values: readonly string[] | null | undefined): string;
/**
 * Reads a text error message from a response-like payload.
 *
 * @example
 * ```ts
 * responseErrorMessage({ error: { message: 'Rate limited' } });
 * // 'Rate limited'
 * ```
 */
export declare function responseErrorMessage(payload: TextResponsePayload | null): string | null;
/**
 * Reads direct or nested output text from a response-like payload.
 *
 * @example
 * ```ts
 * responseOutputText({ output_text: ' Done ' });
 * // 'Done'
 * ```
 */
export declare function responseOutputText(payload: TextResponsePayload | null): string | null;
/**
 * Parses a JSON array of strings or a line/comma-separated list into strings.
 *
 * @example
 * ```ts
 * parseStringList('["seo", "content"]');
 * // ['seo', 'content']
 * ```
 */
export declare function parseStringList(text: string): string[];
/**
 * Parses JSON text after removing an optional Markdown JSON code fence.
 *
 * @example
 * ```ts
 * parseJsonObjectText('```json\\n{"ok":true}\\n```');
 * // { ok: true }
 * ```
 */
export declare function parseJsonObjectText(text: string): unknown;
/**
 * Extracts nested `output_text` content items from an array response shape.
 *
 * @example
 * ```ts
 * outputItemsText([{ content: [{ type: 'output_text', text: 'Hello' }] }]);
 * // 'Hello'
 * ```
 */
export declare function outputItemsText(output: unknown): string;
export { truncateText };
````

<a id="pure-auth"></a>

## @db3.ai/pure/auth

### @db3.ai/pure/auth

```typescript
export { bearerToken } from '@db3.ai/pure/http';
```

<a id="pure-collections"></a>

## @db3.ai/pure/collections

### @db3.ai/pure/collections

````typescript
/**
 * Removes exact duplicate strings while keeping the first occurrence order.
 *
 * @example
 * ```ts
 * uniqueStrings(['alpha', 'beta', 'alpha']);
 * // ['alpha', 'beta']
 * ```
 */
export declare function uniqueStrings(values: readonly string[]): string[];
/**
 * Normalizes whitespace and removes case-insensitive duplicate strings.
 *
 * @example
 * ```ts
 * uniqueNormalizedStrings([' SEO  Agency ', 'seo agency', 'AI']);
 * // ['SEO Agency', 'AI']
 * ```
 */
export declare function uniqueNormalizedStrings(values: readonly string[]): string[];
export interface SelectedStringsResult {
    values: string[];
    invalid: string[];
}
export type SelectedOrAllStringsResult = SelectedStringsResult;
/**
 * Selects requested values from a saved option list and reports unknown values.
 *
 * @example
 * ```ts
 * selectedStrings([' seo agency '], ['SEO Agency', 'Developers']);
 * // { values: ['SEO Agency'], invalid: [] }
 * ```
 */
export declare function selectedStrings(selected: readonly string[], available: readonly string[] | null | undefined): SelectedStringsResult;
/**
 * Selects requested values from a saved option list, or returns all saved options when no selection is supplied.
 *
 * @example
 * ```ts
 * selectedOrAllStrings([' seo agency '], ['SEO Agency', 'Developers']);
 * // { values: ['SEO Agency'], invalid: [] }
 * ```
 */
export declare function selectedOrAllStrings(selected: readonly string[] | undefined, available: readonly string[] | null | undefined): SelectedStringsResult;
````

<a id="pure-dates"></a>

## @db3.ai/pure/dates

### @db3.ai/pure/dates

````typescript
/**
 * Converts a Date or parseable date string to an ISO timestamp.
 *
 * @example
 * ```ts
 * isoDate('2026-01-01T00:00:00Z');
 * // '2026-01-01T00:00:00.000Z'
 * ```
 */
export declare function isoDate(value: Date | string | null | undefined): string | null;
/**
 * Adds whole calendar days to a date.
 *
 * @example
 * ```ts
 * addDays(new Date('2026-01-01T12:00:00Z'), 1).getDate();
 * // 2
 * ```
 */
export declare function addDays(date: Date, days: number): Date;
/**
 * Formats a Date as YYYY-MM-DD in local calendar time.
 *
 * @example
 * ```ts
 * formatDate(new Date(2026, 0, 5));
 * // '2026-01-05'
 * ```
 */
export declare function formatDate(date: Date): string;
/**
 * Converts a numeric or numeric-string id to a finite number.
 *
 * @example
 * ```ts
 * numericId('42');
 * // 42
 * ```
 */
export declare function numericId(value: number | string | null | undefined): number | null;
````

<a id="pure-errors"></a>

## @db3.ai/pure/errors

### @db3.ai/pure/errors

````typescript
/**
 * Reads a public API error message from an unknown response body.
 *
 * @example
 * ```ts
 * apiErrorMessage({ message: 'Try again' }, 'Request failed');
 * // 'Try again'
 * ```
 */
export declare function apiErrorMessage(result: unknown, fallback: string): string;
/**
 * Converts an unknown thrown value into a displayable message.
 *
 * @example
 * ```ts
 * unknownErrorMessage(new Error('Nope'));
 * // 'Nope'
 * ```
 */
export declare function unknownErrorMessage(error: unknown): string;
/**
 * Returns true for database-driver errors that may expose SQL internals.
 *
 * @example
 * ```ts
 * isSqlError({ code: 'ER_DUP_ENTRY' });
 * // true
 * ```
 */
export declare function isSqlError(error: unknown): boolean;
/**
 * Decides whether exact SQL error details can be shown for an environment name.
 *
 * @example
 * ```ts
 * shouldExposeSqlErrorDetails('production');
 * // false
 * ```
 */
export declare function shouldExposeSqlErrorDetails(environment?: string): boolean;
/**
 * Returns true only when the runtime has explicitly opted into development behavior.
 *
 * @example
 * ```ts
 * isDevelopmentEnvironment(undefined);
 * // false
 * ```
 */
export declare function isDevelopmentEnvironment(environment?: string): boolean;
/**
 * Converts a SQL driver error into a public message, hiding details in production.
 *
 * @example
 * ```ts
 * publicSqlErrorMessage({ code: 'ER_DUP_ENTRY' }, { environment: 'production' });
 * // 'A database error occurred.'
 * ```
 */
export declare function publicSqlErrorMessage(error: unknown, options?: {
    environment?: string;
    productionMessage?: string;
}): string | null;
````

<a id="pure-http"></a>

## @db3.ai/pure/http

### @db3.ai/pure/http

````typescript
/**
 * Extracts a bearer token from an Authorization header value.
 *
 * @example
 * ```ts
 * bearerToken('Bearer sk_test_123');
 * // 'sk_test_123'
 * ```
 */
export declare function bearerToken(header: string | readonly string[] | undefined): string | null;
/**
 * Returns the standard application error code for an HTTP status.
 *
 * @example
 * ```ts
 * errorCodeForStatus(404);
 * // 'not_found'
 * ```
 */
export declare function errorCodeForStatus(statusCode: number): string;
/**
 * Allows only same-site redirect paths and blocks selected prefixes.
 *
 * @example
 * ```ts
 * safeRedirectPath('/app/dashboard', ['/auth/']);
 * // '/app/dashboard'
 * ```
 */
export declare function safeRedirectPath(path: unknown, blockedPrefixes?: readonly string[]): string | null;
````

<a id="pure-records"></a>

## @db3.ai/pure/records

### @db3.ai/pure/records

````typescript
/**
 * Checks whether a value is a plain object-like record, excluding arrays and null.
 *
 * @example
 * ```ts
 * isRecord({ message: 'Saved' });
 * // true
 * ```
 */
export declare function isRecord(value: unknown): value is Record<string, unknown>;
/**
 * Returns the input as a record, or an empty record when it is not object-like.
 *
 * @example
 * ```ts
 * recordFromUnknown(null);
 * // {}
 * ```
 */
export declare function recordFromUnknown(value: unknown): Record<string, unknown>;
/**
 * Reads and trims a string field from a record, falling back when it is missing or blank.
 *
 * @example
 * ```ts
 * stringField({ email: ' steve@example.com ' }, 'email');
 * // 'steve@example.com'
 * ```
 */
export declare function stringField(body: Record<string, unknown>, field: string, fallback?: string): string;
/**
 * Reads a boolean field from a record, falling back when the value is not boolean.
 *
 * @example
 * ```ts
 * booleanField({ includeSubdomains: true }, 'includeSubdomains', false);
 * // true
 * ```
 */
export declare function booleanField(body: Record<string, unknown>, field: string, fallback: boolean): boolean;
/**
 * Reads a finite number field from a record, falling back when it is missing or invalid.
 *
 * @example
 * ```ts
 * numberField({ limit: 25 }, 'limit', 10);
 * // 25
 * ```
 */
export declare function numberField(body: Record<string, unknown>, field: string, fallback: number): number;
/**
 * Returns a non-empty string value, or null for anything else.
 *
 * @example
 * ```ts
 * stringValue('headline');
 * // 'headline'
 * ```
 */
export declare function stringValue(value: unknown): string | null;
/**
 * Trims a string-like value, returning the fallback for non-strings.
 *
 * @example
 * ```ts
 * trimmedStringValue('  launch plan  ');
 * // 'launch plan'
 * ```
 */
export declare function trimmedStringValue(value: unknown, fallback?: string): string;
/**
 * Converts finite numbers or numeric strings into a number, otherwise null.
 *
 * @example
 * ```ts
 * numberValue('42');
 * // 42
 * ```
 */
export declare function numberValue(value: unknown): number | null;
/**
 * Returns an ISO string for Date inputs or a non-empty string as supplied.
 *
 * @example
 * ```ts
 * dateTimeStringValue(new Date('2026-01-01T00:00:00.000Z'));
 * // '2026-01-01T00:00:00.000Z'
 * ```
 */
export declare function dateTimeStringValue(value: unknown): string | null;
/**
 * Reads a nested record field, falling back to an empty record.
 *
 * @example
 * ```ts
 * nestedRecord({ keyword_data: { keyword: 'seo' } }, 'keyword_data');
 * // { keyword: 'seo' }
 * ```
 */
export declare function nestedRecord(value: Record<string, unknown>, field: string): Record<string, unknown>;
/**
 * Parses JSON text and requires the result to be an object record.
 *
 * @example
 * ```ts
 * parseJsonRecord('{"job":"crawl"}');
 * // { job: 'crawl' }
 * ```
 */
export declare function parseJsonRecord(input: string, message?: string): Record<string, unknown>;
/**
 * Returns a finite number, or null for missing and non-number values.
 *
 * @example
 * ```ts
 * optionalNumber(12.5);
 * // 12.5
 * ```
 */
export declare function optionalNumber(value: unknown): number | null;
/**
 * Returns a string that contains non-whitespace characters, preserving the original value.
 *
 * @example
 * ```ts
 * optionalString(' keyword ');
 * // ' keyword '
 * ```
 */
export declare function optionalString(value: unknown): string | null;
/**
 * Checks for a promise-like value with a callable `then` method.
 *
 * @example
 * ```ts
 * isPromiseLike(Promise.resolve('done'));
 * // true
 * ```
 */
export declare function isPromiseLike(value: unknown): value is PromiseLike<unknown>;
/**
 * Checks for a promise value with a callable `finally` method.
 *
 * @example
 * ```ts
 * isFinallyPromise(Promise.resolve('done'));
 * // true
 * ```
 */
export declare function isFinallyPromise(value: unknown): value is Promise<unknown>;
````

<a id="pure-strings"></a>

## @db3.ai/pure/strings

### @db3.ai/pure/strings

````typescript
/**
 * Collapses runs of whitespace into a single space and trims the result.
 *
 * @example
 * ```ts
 * normalizeWhitespace('  SEO\\n  content   plan  ');
 * // 'SEO content plan'
 * ```
 */
export declare function normalizeWhitespace(input: string): string;
/**
 * Builds a case-insensitive comparison key for human-entered strings.
 *
 * @example
 * ```ts
 * normalizedKey('  Flex   AI  ');
 * // 'flex ai'
 * ```
 */
export declare function normalizedKey(input: string): string;
/**
 * Converts an identifier or slug into display-friendly title text.
 *
 * @example
 * ```ts
 * startCase('targetAudiencePhrases');
 * // 'Target Audience Phrases'
 * ```
 */
export declare function startCase(input: string): string;
/**
 * Converts a display string or identifier into snake_case.
 *
 * @example
 * ```ts
 * snakeCase('Target Audience Phrases');
 * // 'target_audience_phrases'
 * ```
 */
export declare function snakeCase(input: string): string;
/**
 * Converts a model or class name into lower-case prose for messages.
 *
 * @example
 * ```ts
 * displayNameFromIdentifier('PasswordResetToken');
 * // 'password reset token'
 * ```
 */
export declare function displayNameFromIdentifier(input: string): string;
/**
 * Removes blank edge lines and trims each line of a multi-line comment.
 *
 * @example
 * ```ts
 * normalizeDatabaseComment('  First line\\r\\n  Second line  ');
 * // 'First line\\nSecond line'
 * ```
 */
export declare function normalizeDatabaseComment(input: unknown): string | null;
/**
 * Returns a string capped at the requested length, trimming trailing whitespace.
 *
 * @example
 * ```ts
 * truncateText('organic growth workflow', 14);
 * // 'organic growth'
 * ```
 */
export declare function truncateText(value: string, maxLength: number): string;
/**
 * Returns a string capped at the requested length, appending an ellipsis when truncated.
 *
 * @example
 * ```ts
 * truncateWithEllipsis('organic growth workflow', 14);
 * // 'organic growth...'
 * ```
 */
export declare function truncateWithEllipsis(value: string, maxLength: number): string;
/**
 * Escapes text for safe placement inside HTML text or attribute values.
 *
 * @example
 * ```ts
 * escapeHtml('Reset "A&B" <now>');
 * // 'Reset &quot;A&amp;B&quot; &lt;now&gt;'
 * ```
 */
export declare function escapeHtml(input: string): string;
/**
 * Trims strings, removes empty entries, and caps the list length.
 *
 * @example
 * ```ts
 * limitedStrings([' SEO ', '', 'AI'], 1);
 * // ['SEO']
 * ```
 */
export declare function limitedStrings(values: readonly string[], limit?: number): string[];
/**
 * Counts whitespace-separated words in a string, returning zero for nullish text.
 *
 * @example
 * ```ts
 * wordCount('organic growth workflow');
 * // 3
 * ```
 */
export declare function wordCount(value: string | null | undefined): number;
/**
 * Removes a surrounding Markdown JSON code fence from a string.
 *
 * @example
 * ```ts
 * stripJsonCodeFence('```json\\n{"ok":true}\\n```');
 * // '{"ok":true}'
 * ```
 */
export declare function stripJsonCodeFence(input: string): string;
````

<a id="pure-ulid"></a>

## @db3.ai/pure/ulid

### @db3.ai/pure/ulid

````typescript
/**
 * Creates a canonical, crypto-random ULID string.
 *
 * The timestamp portion is encoded from the provided date or timestamp, and the
 * random portion is filled with `crypto.getRandomValues()`.
 *
 * @example
 * ```ts
 * const id = ulid();
 * ```
 */
export declare function ulid(date?: Date | number): string;
/**
 * Returns true when a value is a valid ULID-shaped string.
 *
 * ULIDs use Crockford Base32 and exclude I, L, O, and U.
 */
export declare function isUlid(value: unknown): value is string;
/**
 * Extracts the timestamp from a ULID as a `Date`.
 *
 * Accepts lowercase input, since `isUlid` does.
 *
 * @example
 * ```ts
 * const createdAt = ulidTime('01J9XQ3Z5H8B2M4N6P7Q9R0S1T');
 * ```
 */
export declare function ulidTime(value: string): Date;
````

<a id="pure-urls"></a>

## @db3.ai/pure/urls

### @db3.ai/pure/urls

````typescript
/**
 * Parses an optional valid port from a string.
 *
 * @example
 * ```ts
 * optionalPort('5174');
 * // 5174
 * ```
 */
export declare function optionalPort(input: string | undefined): number | undefined;
/**
 * Normalizes a website URL or domain to a bare hostname without a leading `www.`.
 *
 * @example
 * ```ts
 * normalizeDomainTarget('https://www.example.com/path');
 * // 'example.com'
 * ```
 */
export declare function normalizeDomainTarget(value: string): string | null;
/**
 * Normalizes an absolute URL or bare domain, removing hashes and repeated path
 * slashes.
 *
 * @example
 * ```ts
 * normalizeUrl('example.com//page#section');
 * // 'https://example.com/page'
 * ```
 */
export declare function normalizeUrl(value: string): string;
/**
 * Safely normalizes a URL, resolving relative paths and collapsing repeated
 * path slashes.
 *
 * @example
 * ```ts
 * tryNormalizeUrl('/pricing//plans#top', 'https://example.com');
 * // 'https://example.com/pricing/plans'
 * ```
 */
export declare function tryNormalizeUrl(value: string, baseUrl?: string): string | null;
````

## Additional source-backed examples

### examples/runNoteTags.ts

```typescript
import { selectNoteTags } from './selectNoteTags';

/** Exercises normalized selection, rejected unknown values and valid recovery. */
export function runNoteTags() {
	let invalidRejected = false;
	try { selectNoteTags(['Administrator']); } catch { invalidRejected = true; }
	return { tags: selectNoteTags([' client ', 'CLIENT', ' internal ']), invalidRejected, repaired: selectNoteTags(['Internal']) };
}

console.log(JSON.stringify(runNoteTags(), null, 2));
```

## Behavioural verification
Normalizes allowed note tags, rejects unknown values and recovers with a valid selection.
- Behaviour test: `packages/pure/tests/noteTags.test.ts`
- Repository test command (framework checkout only): `npm test --workspace @platform/pure`
- In an installed application, use the walkthrough commands instead of this repository test.
- Expected outcome: The note-tag test passes using public Pure imports.
- Environment: Node.js and Vitest; no App, SQL or provider.

## Related documentation
- [@db3.ai/app](https://db3.ai/docs/package-app.md): The backend runtime: application services, field-aware records, durable work and optional web delivery.
- [Validate application input](https://db3.ai/docs/validation.md): Check a note request, return useful field errors and make the boundary between validation, conversion and authorization explicit.
- [Application URLs](https://db3.ai/docs/url.md): Give email, workers and HTTP routes one trusted application address. A URL resolver is not a redirect policy.

## Framework-owned source: `packages/pure/README.md`

This is the exact source document captured by the documentation build. Use it for detailed API and workflow guidance, subject to the public package exports and behavioural evidence identified above.

````markdown
# @db3.ai/pure

Environment-independent TypeScript utilities shared by DB3 framework
packages and applications.

## Installation

For a local preview, use the supplied Pure tarball rather than an unpublished
registry version. After installing it, copy `node_modules/@db3.ai/pure/examples/`
into your app's `examples/` and run `npx tsx examples/runNoteTags.ts` with the
development tools from the website's Installation page. It normalizes allowed
tags, rejects an unknown option and recovers with a valid choice. The exact
consumer test is `tests/noteTags.test.ts`; copy it into your app's `tests/`.

The helpers do not replace request validation or authorization. In particular,
`selectedStrings()` reports unknown values in `invalid` but retains them in
`values`. Check `invalid` before saving. These functions do not need an `App`,
database, provider key or HTTP server.

After the first public release, install the utilities with:

```sh
npm install @db3.ai/pure
```

## Publishing status

The staging workflow produces a consumer-verifiable public package artifact,
under the selected MIT license. The target package name is `@db3.ai/pure` and
the configured public source target is `github.com/db3ai/framework`. Neither
metadata nor a successful local package test proves that source and npm versions
are public. Verify npm access, the public repository and trusted-publisher
configuration before publishing. Contributors follow `docs/framework-release.md`.

## Consumer package artifacts

Run `npm run framework:package` and `npm run framework:package:test` from the
repository root. The staged Pure artifact is written to
`dist/framework-packages/pure`; the verification command packs it alongside
App and installs both tarballs in a temporary consumer. The workspace manifest
keeps source exports for monorepo development, while the ordinary staged
manifest exposes compiled JavaScript and declarations under `@db3.ai/pure` and
omits the current private repository identity. Release-mode staging accepts only
the exact dedicated public framework repository, while candidate preparation
requires the checked-in version to match the requested tag. Always prepare Pure
before App. These commands never publish packages.

Once the public GitHub source exists, pass its exact canonical URL with `--repository-url` or
`DB3_FRAMEWORK_REPOSITORY_URL`; that explicit release mode adds repository
metadata and enables npm provenance. See the App package README for the complete
release command.

Dependency-light utilities shared by framework packages and apps.

Use this package for deterministic helpers that should not pull in runtime services:

- strings and display names
- URL helpers
- dates
- records and plain-object helpers
- error normalization
- small auth and HTTP types/helpers
- ULID generation and validation

Do not put database access, request context, queue behavior, mail transports, app models, or product-specific rules here.

Useful check:

```sh
npm run check --workspace packages/pure
```

Promote a helper into this package only when more than one package or app can use it without dragging in backend runtime dependencies.
````

## Guidance for AI tools
Use the documented public import `@db3.ai/pure` and its exported types. Prefer the source-backed examples and behavioural outcomes above over invented APIs or source-relative internal imports.
