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

@absolutejs/secure-messaging

v0.6.1

Published

Provider-neutral secure conversation orchestration for AbsoluteJS E2EE providers and untrusted delivery services.

Readme

@absolutejs/secure-messaging

Provider-neutral secure conversation orchestration for AbsoluteJS. It composes a MessagingProvider, untrusted DeliveryService, application policy, and durable atomic state/outbox/replay store behind one API. Cryptography remains in interchangeable @absolutejs/e2ee-* providers.

The confidentiality mode is mandatory and explicit. strict-e2ee means only verified participant devices may decrypt. managed-recovery is a separate conversation contract and requires a visibly identified recovery authority in the surrounding application. This package never silently changes modes.

import { createSecureMessagingClient } from "@absolutejs/secure-messaging";

const messaging = createSecureMessagingClient({
  delivery,
  deviceCredential,
  keyPackageDirectory,
  membershipPolicy: {
    authorize: ({ target }) => approvedIdentities.has(target.identityId),
    reviewInvitation: ({ members }) =>
      members.every(({ identityId }) => approvedIdentities.has(identityId))
        ? "accept"
        : "pending",
  },
  policy: {
    authorize: ({ direction, purpose, securityEpoch, senderDeviceId }) =>
      allowedPurposes.has(purpose) &&
      securityEpoch >= minimumEpoch &&
      (direction === "outbound" || trustedDevices.has(senderDeviceId)),
    maximumFrameBytes: 1_572_864,
    maximumFutureSkewMs: 300_000,
    maximumMessageBytes: 1_048_576,
    maximumTtlMs: 86_400_000,
    securityMode: "strict-e2ee",
  },
  provider,
  store,
});

For managed-recovery, also provide exactly one recovery verifier. A recovery request is short-lived and binds the conversation, subject identity, replacement device credential, and every lost device ID. After the configured authority and local membership policy both approve it, recoverMember() adds the replacement KeyPackage and removes the lost leaves in one MLS commit. Strict-E2EE clients reject recovery-authority configuration.

Version 0.3.0 includes an explicit invitation inbox, durable MLS membership maintenance. A cryptographically valid Welcome can be accepted immediately, held as an inert pending-invitation, or durably rejected. Pending conversations cannot send, invite, remove members, self-update, or process conversation traffic. Member removal and self-update policy checks occur before MLS mutation, and the resulting group state and retryable commit messages use one atomic store commit. Managed state-loss recovery uses RFC 9750's recovery-after-state-loss model and never hands serialized live group state to the recovery authority. Attachments, abuse reports and federation live in separate packages and are not claimed by this core package.

Version 0.4.0 adds expectedSecurityEpoch for sensitive application messages. Use the epoch returned by removeMembers(), recoverMember(), or selfUpdate() when sending an attachment replacement or another action that must occur in that exact post-commit roster. The client checks the precondition before protecting or persisting the message and returns the authenticated securityEpoch on success. This follows RFC 9420's epoch model: fresh Commit entropy is available only to members of the new epoch. The real MLS integration suite sends a strict @absolutejs/secure-transfer replacement in that epoch, verifies the replacement device can decode it, and verifies the removed device cannot process the same application ciphertext.

Version 0.5.0 runs inbound application authorization only after the selected E2EE provider has authenticated and processed the frame. The policy receives the authenticated purpose and security epoch; for application messages, messageBytes is the decrypted plaintext size. A rejection discards the mutated in-memory session and requires a durable reload, so an unauthenticated envelope cannot trigger authorization side effects.

Version 0.5.1 adds receiveAndHandle() for request/receipt protocols. Its handler runs after MLS authentication and application policy, but before the inbound replay receipt or transport cursor is committed. Replies returned by the handler are protected at the same MLS epoch and placed in the durable outbox in the same store commit as the inbound receipt and advanced provider state. The method wipes inbound and reply plaintext and returns message IDs rather than plaintext. Use the authenticated request ID as the downstream idempotency key: an application side effect can be retried if the process exits before the atomic commit.

Version 0.6.0 exports SecureMessagingDurabilityUncertainError for the storage boundary where a mutation may have applied but its durability acknowledgement was lost. Callers must resolve the authoritative store, reload state, and retry only when the expected revision or effect is absent. The error contains no conversation, message, queue, or provider data.

Version 0.6.1 adds resolveSecureMessagingStoreCommit(). After selecting the authoritative store, pass it the intended conversation and expected revision. It returns applied only when the complete stored conversation—including sealed state—matches, retry only when the prior revision is still authoritative, and conflict for every other state. Associated replay and outbox effects follow the store's atomic commit contract.

Security boundaries

  • Delivery sees ciphertext and minimum routing metadata, never conversation keys.
  • Unknown fields, malformed frames, metadata substitution, replay-ID conflicts, unauthorized messages, and processing errors fail closed without acknowledgement.
  • Inbound policy.authorize may perform audit or approval effects because it is called only after cryptographic authentication. Treat delivery metadata and pre-decryption frame fields as untrusted everywhere else.
  • receiveAndHandle() transfers ownership of its handler's reply buffers to the client and wipes them. Handler side effects must be idempotent because a crash after the effect but before the store commit causes safe redelivery.
  • Exact duplicates and already-expired frames can be acknowledged without being processed.
  • The store must atomically commit sealed provider state, its compare-and-set revision, an inbound replay receipt, and outbound queue entries. Splitting these writes can cause message loss, replay lockout, or MLS state divergence.
  • recordInbound must durably preserve a rejected Welcome receipt without creating conversation state. removeConversation must compare-and-delete the exact revision while preserving replay receipts. These properties prevent a rejected invite from reappearing and prevent acceptance/rejection races.
  • Invitation review receives identities verified by the selected E2EE provider, but applications should default unknown or unexpected groups to pending and require an authenticated, phishing-resistant approval ceremony before calling acceptInvitation.
  • Removing a device prevents it from decrypting future epochs; it cannot erase plaintext or keys the device already possessed. Removed devices are not sent the removal commit.
  • Recovery grants authorize membership replacement; they do not decrypt history. The authority verifier must authenticate the complete request, enforce its own approval ceremony, reject revoked/expired grants, and maintain an audit trail. Recovery cannot recover data that no surviving member or encrypted archive has.
  • Outbox delivery is at-least-once. A crash after transport acceptance but before outbox removal can resend ciphertext; recipients handle the exact duplicate through the durable receipt committed with their new sealed state.
  • A state conflict closes and removes the in-memory session. Reload durable state before any further operation.
  • A SecureMessagingDurabilityUncertainError means success and failure are both possible. Never retry blindly: resolve the authoritative store and inspect the expected revision, replay receipt, or outbox effect first.
  • Push notifications should carry only an opaque wake-up token.

See SECURITY.md before production use.

License

Apache-2.0