npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@plasius/storage

v1.3.5

Published

Azure storage, immutable asset-version, and schema-backed JSON packet primitives for Plasius projects

Readme

@plasius/storage

npm version Build Status coverage License Code of Conduct Security Policy Changelog

Public package containing shared Azure storage helpers and server-side immutable asset-version and schema-backed JSON packet primitives for Plasius services.

Install

npm install @plasius/storage

Azure Files Usage

import { uploadUserImageShare } from "@plasius/storage";

await uploadUserImageShare("user-123", 1, Buffer.from("avatar"), "image/png");

uploadUserImageShare() supports image/png, image/jpeg, image/jpg, image/webp, image/gif, and image/avif, and it normalizes unsafe userId values before using them as Azure Files directory names.

Immutable Asset Versions

The @plasius/storage/immutable-assets subpath is Node-only. It implements conditional, digest-verified Azure Blob mechanics behind injected structural ports; it is intentionally unavailable to browser bundles and does not create credentials or Azure clients.

Its primary exports are:

  • createImmutableAssetStore(config) for a service with distinct intake and runtime scopes;
  • createImmutableAssetVersion(container, input, options?) for conditional, manifest-last creation followed by complete verification;
  • verifyImmutableAssetVersion(container, identity, options?) for an explicit full-version re-read;
  • readImmutableAssetVersionFile(container, identity, relativePath, options?) for marker-first exact file access;
  • BlobContainerPort and BlockBlobClientPort structural adapter types;
  • immutable identity, input, manifest, receipt, options, store, diagnostic, and error-code types; and
  • ImmutableAssetStorageError for bounded, typed failures.

Import the API only from server-side Node code:

import {
  createImmutableAssetStore,
  createImmutableAssetVersion,
  verifyImmutableAssetVersion,
  readImmutableAssetVersionFile,
  ImmutableAssetStorageError,
  type BlobContainerPort,
} from "@plasius/storage/immutable-assets";

IMMUTABLE_VERSION_MANIFEST_PATH is the fixed marker path, and MAX_IMMUTABLE_VERSION_FILES is the 513-file total ceiling.

Use a private intake container for unpromoted candidates and a private runtime container for immutable versions that may be referenced by the promoted model catalog. The host constructs the Azure adapters, supplies an abort signal/deadline, and chooses the container for each operation.

The configured store exposes stageVersion, publishVersion, verifyVersion, and readVersionFile. stageVersion targets the intake scope; publishVersion targets the runtime scope. Verification and reads require an explicit scope, so a caller cannot silently cross the intake/runtime boundary.

Version roots

| Asset kind | Immutable root | | --- | --- | | Model | models/{id}/versions/{version} | | GPU interface | gpu-interfaces/{id}/versions/{version} | | WGSL shader | shaders/{id}/versions/{version} | | Shader style profile | shader-style-profiles/{id}/versions/{version} | | Qualification evidence | shader-evidence/{id}/versions/{version} |

Every complete version has the fixed marker _plasius/version-manifest.json. A version may contain at most 513 files in total: one marker and up to 512 manifest-declared payloads.

Write contract

The immutable write operation:

  1. validates the identity, paths, content types, package limits, and byte budgets before storage effects;
  2. computes lowercase SHA-256, exact length, and protocol-owned metadata from the supplied bytes;
  3. creates payloads with If-None-Match: *;
  4. accepts an existing blob as an idempotent replay only after its complete bytes, length, content type, digest, and metadata match;
  5. writes _plasius/version-manifest.json last; and
  6. re-reads and verifies the marker and every declared payload before returning a verified receipt.

The receipt is evidence of immutable storage verification only. It contains no Blob URL or SAS token and grants no catalog or runtime authority.

Read contract

A read requires a supported kind, exact asset ID/version, and a normalized relative path. It verifies the fixed marker first, requires that the marker declares the path, then downloads and verifies the payload. Traversal, undeclared paths, mutable aliases such as latest, raw blob names, and arbitrary Blob/SAS URLs fail closed.

Failure and lifecycle retention

Operations return typed storage diagnostics for invalid input, immutable conflict, integrity mismatch, incomplete versions, timeout/abort, dependency failure, and undeclared reads. Callers own bounded retry policy; the package does not hide dependency failures behind internal retry loops.

Before the marker exists, a failed attempt is unreachable to marker-first readers. This API intentionally has no delete authority: payloads from an interrupted attempt are retained because a concurrent completion marker may have adopted them. The host may apply a separately authorized lifecycle policy only after proving an unreachable candidate is neither complete nor catalog referenced. Product rollback changes a catalog pointer elsewhere; it never overwrites or deletes these bytes.

Ownership and rollout boundary

This package owns Blob paths, conditional creation, integrity metadata, manifest-last completion, complete verification, and exact marker-first reads. The model-storage/site layer continues to own:

  • private-container configuration, credentials, authentication, authorization, tenant policy, and audit;
  • catalog rows, channel compare-and-swap, promotion, discovery, and rollback;
  • shader/model schemas, reflection, ABI and semantic compatibility, admission, and qualification-evidence policy;
  • evaluation of feature flag asset.pipeline.shader-store.enabled; and
  • evaluation of capability gpu.shader.style.select for user-visible style discovery and selection.

The feature flag is the runtime/public-submission rollout control. The capability does not grant promotion or storage access and is not required for default-profile rendering. Neither control is evaluated by this package.

For the complete protocol and security requirements, see ADR-0003, TDR-0001, and SECURITY.md.

Immutable Schema-Backed JSON Packets

The @plasius/storage/immutable-json-packets subpath is Node-only. It stores privacy-safe, structured JSON packets behind injected Azure Blob-compatible ports and provides coordination records for bounded processors.

import {
  createImmutableJsonPacketStore,
  type JsonPacketBlobContainerPort,
} from "@plasius/storage/immutable-json-packets";
import {
  FeedbackBugPacketSchema,
  FeedbackProcessorCheckpointSchema,
} from "@plasius/schema";

declare const privateFeedbackContainer: JsonPacketBlobContainerPort;
declare const structuredPacket: unknown;
declare const requestSignal: AbortSignal;

const feedbackPackets = createImmutableJsonPacketStore({
  container: privateFeedbackContainer,
  kinds: {
    bug: {
      prefix: "feedback/bugs",
      packetSchema: FeedbackBugPacketSchema,
      checkpointSchema: FeedbackProcessorCheckpointSchema,
      timeIndex: {
        prefix: "feedback-index/bugs",
        timestampField: "acceptedAt",
        partition: "hour",
      },
      safeDeadLetterCodes: [
        "CLASSIFIER_UNAVAILABLE",
        "PACKET_SCHEMA_REJECTED",
      ],
    },
  },
  timeoutMs: 30_000,
  maxPacketBytes: 256 * 1024,
  maxListPageItems: 100,
  maxListPageBytes: 4 * 1024 * 1024,
});

const receipt = await feedbackPackets.writePacket(
  "bug",
  "bug_01j1te5t000000000000000001",
  structuredPacket,
  { signal: requestSignal }
);

const page = await feedbackPackets.listPacketPage("bug", {
  maxItems: 100,
  maxBytes: 4 * 1024 * 1024,
  signal: requestSignal,
});
const packets = await Promise.all(
  page.packets.map(({ packetId }) =>
    feedbackPackets.readPacket("bug", packetId, { signal: requestSignal })
  )
);

const hour = await feedbackPackets.readPacketTimeWindow("bug", {
  windowStart: "2026-07-18T12:00:00.000Z",
  windowEnd: "2026-07-18T13:00:00.000Z",
  maxItems: 10_000,
  maxBytes: 4 * 1024 * 1024,
  signal: requestSignal,
});

const windowSnapshots = await feedbackPackets.listPacketTimeWindows("bug", {
  windowStart: "2026-07-11T12:00:00.000Z",
  windowEnd: "2026-07-18T13:00:00.000Z",
  partition: "hour",
  maxItems: 169,
  maxBytes: 4 * 1024 * 1024,
  signal: requestSignal,
});

The example schema exports are supplied by the consuming application/package; this package accepts their structural validate() and getPiiAudit() surface. Schema registration fails closed unless its PII audit is empty.

Storage contract

  • Packet kinds select fixed, non-overlapping prefixes at store construction. Individual operations cannot provide Blob paths, prefixes, URLs, containers, or credentials.
  • writePacket() accepts a structured value only. There is deliberately no raw JSON string, request body, Buffer, arbitrary metadata, or generic object upload API.
  • Plain safe JSON is snapshotted before and after schema validation. Cycles, getters, symbols, custom prototypes, sparse arrays, non-finite numbers, excessive bounds, unsafe or content-shaped object keys, narrative/identity/browser fields, and deterministic sensitive-value patterns fail before Blob access. Array length/member bounds are checked before keys are enumerated or output storage is allocated.
  • Canonical packet bytes and protocol metadata are created with If-None-Match: *. Only Blob's precise already-exists/precondition signals enter collision reconciliation; other 409 responses remain dependency failures. A collision is an idempotent replay only when the entire stored representation matches.
  • Receipts contain safe IDs, schema identity, SHA-256, length, ETag, and replay status. They contain no packet value, Blob URL/path, credentials, or provider response. Provider ETags must be bounded printable values before they can enter a receipt or subsequent compare-and-swap.
  • readPacket() requires an exact configured kind and safe packet ID, then verifies the canonical bytes, metadata, digest, ETag, envelope, and schema.
  • listPacketPage() asks the injected Azure-compatible ContainerClient for exactly one bounded flat page under the kind's fixed {prefix}/packets/ root. Callers cannot provide a prefix, path, container, or URL. The method validates every listed name, content type, ETag, complete protocol metadata record, schema identity, digest, item count, and aggregate declared-byte budget before returning sorted descriptors.
  • List results contain only safe packet IDs, schema identity, SHA-256, and byte length. They never contain packet values, Blob names/URLs, provider tokens, account correlation, pseudonyms, narrative, or arbitrary metadata. Payloads still pass through readPacket() so full bytes, integrity, and the registered schema are checked at the consumer boundary.
  • The optional cursor is a deterministic, bounded, opaque, kind-bound wrapper around Azure's continuation. It resumes only the same bounded traversal and is not a durable snapshot or an ingestion checkpoint. Processors must start a fresh traversal when reconciling new or late packets and use immutable output manifests/checkpoint CAS—not the list cursor—as their correctness boundary.
  • A kind that configures timeIndex gains an append-only accepted-time head for each exact UTC hour or day. writePacket() writes the immutable packet first and returns success only after its safe index entry is visible. An exact replay repairs a missing entry; hosts must keep an outbox and retry an ambiguous failure because Blob cannot atomically commit the two records.
  • readPacketTimeWindow() reads one aligned head and every referenced packet, verifies both integrity boundaries, and returns one complete canonically ordered result or fails without partial output. listPacketTimeWindows() derives a bounded set of exact head paths and obtains properties only for those paths; it never flat-lists retained content. The method is not a stateful change feed: hosts compare each stable opaque snapshot with their own checkpoint, and a late packet changes the affected snapshot. Provider properties and metadata are admitted only as bounded plain data descriptors; accessors and dependency traps are never invoked and fail with fixed redacted corruption errors.
  • Window heads are capped at 10,000 entries (and may be reduced by the store's configured manifest-entry ceiling) in addition to encoded-byte and operation-deadline bounds.
  • Index heads contain only server acceptance time, safe packet ID, registered schema identity, digest, and byte length. They contain no packet payload, narrative, reporter correlation, request/browser facts, URL, or provider data. The configured timestampField must be server-owned before this API is called.

This is the final structured storage guard, not a free-text PII detector. Narrative, screenshots, identity correlation, URLs, locale, and client timestamps must never be passed to it. Upstream services must discard transient narrative after deriving closed classifications.

Processor coordination

  • compareAndSwapCheckpoint() creates with If-None-Match: * or updates with the exact prior ETag. An uncertain retry succeeds only when the current canonical checkpoint is identical.
  • acquireLease() uses a fixed sentinel and a 15–60 second Azure lease. Its returned handle can renew or release without exposing the lease token. Concurrent releases coalesce, an already-lost lease is an idempotent release, and renewal expiry is conservatively based on the request start. A release caller's cancellation or deadline stops only that caller's wait: the bounded provider release remains single-flight until it settles, so an immediate retry cannot launch a second release.
  • writeManifest() stores only a bounded UTC window/revision and sorted packet ID/digest/length facts.
  • writeDeadLetter() stores only a packet ID, startup-allowlisted error code, package-generated canonical server timestamp, bounded attempt, and retryability. The caller cannot supply the timestamp; retries with the same ID and logical facts replay the first server-timestamped record.

The host owns authentication, authorization, private-container and managed-identity configuration, feature flag feedback.reporting.enabled, processor traversal/reconciliation, retry policy, lifecycle/backup retention, and all PII elimination before this API. The package has no logging, delete, generic or caller-prefixed scan, public URL, SAS, credential-construction, or lifecycle-policy surface. Existing write/read-only adapters remain compatible; listPacketPage() fails closed until the injected container also supplies the Azure-compatible flat-list structural method, and listPacketTimeWindows() fails closed until exact Blob getProperties() is available.

For the full decision and protocol, see ADR-0004, ADR-0007, TDR-0002, and SECURITY.md.

Development

npm install
npm run privacy:check
npm run build
npm test
npm run test:privacy
npm run typecheck
npm run lint
npm run test:coverage
npm run audit:all
npm run pack:check

Private-artifact and package policy

Signed contributor agreements and contributor acceptance records are retained in an approved access-controlled system outside source control. A zero-dependency policy gate inspects repository and Git-index path metadata only; it never opens or hashes a suspected private artifact, and rejection messages expose rule counts rather than suspected path values.

privacy:check rejects protected paths in the working tree and proposed Git index. This includes contributor acceptance, signature, submission, and signed agreement record aliases across hierarchical, Windows, and Unicode compatibility path forms. One closed semantic vocabulary recognizes all contributor, CLA, privacy, registry, record-category, wrapper, and numeric terms across separators, case styles, and separator-free forms. Numeric wrappers are decimal runs optionally prefixed by V, version, revision, or generation; literal word prefixes must be followed immediately by digits. Protected families are classified independently of term order, so intervening wrappers, reversed aliases, and a third protected marker cannot turn a private path into an opaque token. Arbitrary substring matches remain outside the closed vocabulary. Explicit process, template, policy, schema, and validator documents, including compact or separated numeric wrappers such as V2 and version2, remain public only when they are terminal files, not record directories. Windows-ignored trailing dots and spaces are removed from each path component only for classification, so a path such as report.csv. is rejected while its raw package identity remains distinct for exact allowlist and collision checks. Policy rejections expose only rule counts; exceptional traversal or verifier failures expose only allowlisted codes, never candidate paths, raw exception messages, or stacks. pack:check applies the same rules to the final npm path manifest, requires the explicit package.json.files allowlist, and rejects any package path not present in the exact public-package allowlist. Raw package identities and cardinality are retained so Unicode-normalized aliases or duplicate members cannot disappear into the allowlist comparison. Public CLA templates remain distributable, but broad legal-directory entries are forbidden.

Every requested npm package inventory is evaluated by the same private-path classifier, including packages rooted below otherwise excluded tool/cache directories. CI runs the path and package gates, and release preparation and publishing fail closed when either policy fails. Node's built-in coverage is exported to LCOV and combined with package coverage so each executable policy boundary remains visible to review. These targeted controls are defense in depth; they do not replace organisation-wide secret scanning, access control, or incident response.

Governance

License

MIT

Release integrity

CI keeps the administrative contributor registry outside Git and npm package artifacts using exact, case-normalised path checks. Pull requests run on GitHub-hosted runners after same-repository admission; protected main CI uses the workflow-restricted self-hosted group. Release preparation and npm publication use GitHub-hosted runners with Node.js 24.18.0 LTS.

Dispatch cd.yml from protected main with phase: prepare. Release metadata lands through a unique pull request. After successful push-triggered CI for the exact merge SHA, the workflow dispatches a separate publish run from that same SHA. Publication fails closed if main, CI evidence, the version, tag, prerelease identity, artifact digests, or npm registry integrity differ.

The read-only validation job runs the repository privacy gate, installs dependencies, validates the package, builds an SBOM, and seals an immutable tarball. The production job runs no package lifecycle or dependency code; it verifies the exact artifact hand-off and publishes that tarball through npm OIDC with provenance. No npm write token or fallback is configured. The trusted publisher must be bound to Plasius-LTD/storage, cd.yml, production, and npm publish. Rollback is to disable cd.yml; never restore token-based publication.