Skip to content

chore: prepare for release v0.2.0 - #59

Merged
aspiers merged 2 commits into
mainfrom
changeset-release/main
Apr 9, 2026
Merged

chore: prepare for release v0.2.0#59
aspiers merged 2 commits into
mainfrom
changeset-release/main

Conversation

@hypercerts-release-bot

Copy link
Copy Markdown

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

epds@0.2.0

Who should read this release

Minor Changes

  • #58 905ad25 Thanks @aspiers! - Longer sign-in codes, optionally mixing letters and numbers.

    Affects: End users, Operators

    End users: depending on how the ePDS instance you sign in to
    is configured, sign-in codes sent to your email may now be longer
    (up to 12 characters) and may include uppercase letters as well as
    digits. Codes of 8 or more characters are displayed grouped in the
    email for readability (e.g. 1234 5678), but you can still paste
    the whole code into the sign-in form as usual — the space is just
    a visual aid.

    Operators: two new environment variables on the auth service —
    OTP_LENGTH (integer, range 4–12, default 8) and OTP_CHARSET
    (numeric (default) or alphanumeric; alphanumeric uses uppercase
    A–Z plus 0–9). Values outside the range cause the service to fail on
    startup. The OTP form fields (input width, pattern, inputmode,
    autocapitalize) adapt automatically from the configured length and
    charset; no template changes are required.

    Operators running custom email templates: the shared email
    helpers now format OTPs with visual grouping when the code is 8
    characters or longer — e.g. 1234 5678 in subject lines and plain
    text, and <span>1234</span><span>5678</span> with CSS spacing in
    HTML so that copy-paste still yields the flat code. If you render
    OTPs yourself rather than going through EmailSender.sendOtpCode(),
    import formatOtpPlain() and formatOtpHtmlGrouped() from
    @certified-app/shared instead of interpolating the raw code.

  • #58 905ad25 Thanks @aspiers! - Choose your own handle when signing up, instead of being given a random one.

    Affects: End users, Client app developers, Operators

    End users: the signup flow now shows a handle picker by default
    instead of assigning a random handle. You can type a custom handle
    and the picker will check availability as you type, or click the
    random-handle button to take what the old flow would have given
    you. The picker now accepts handles as short as 5 characters and
    handles are validated more strictly so that some handles that used
    to be accepted may now be rejected up-front with a clearer error.
    The picker layout has been widened to accommodate long PDS domain
    names without truncation.

    Client app developers (building on top of ePDS): a new
    epds_handle_mode setting controls which variant of the signup
    handle picker is shown. Accepted case-sensitive values:

    • picker — always show the picker, no random option offered.
    • random — always assign a random handle, no picker (the
      pre-0.2.0 behaviour).
    • picker-with-random (default) — show the picker but include a
      "generate random" option.

    The setting is resolved with the following precedence (first
    match wins), falling back to a built-in default:

    1. epds_handle_mode query parameter on the /oauth/authorize
      request.
    2. epds_handle_mode field in the OAuth client metadata JSON
      served at the client's client_id URL.
    3. EPDS_DEFAULT_HANDLE_MODE environment variable on the auth
      service.
    4. Built-in default: picker-with-random.

    This precedence was previously wrong — the env var was consulted
    before the client metadata, so clients could not override a server
    default. If you relied on that bug, your env var setting will now
    be overridden by whatever the client metadata says.

    To force a specific handle mode for users of your app, add the
    field to the client metadata JSON that your client_id URL
    returns, alongside the standard OAuth fields:

    {
      "client_id": "https://example.com/oauth/client-metadata.json",
      "client_name": "Example",
      "redirect_uris": ["https://example.com/oauth/callback"],
      "grant_types": ["authorization_code", "refresh_token"],
      "response_types": ["code"],
      "scope": "atproto transition:generic",
      "token_endpoint_auth_method": "none",
      "application_type": "web",
      "dpop_bound_access_tokens": true,
      "epds_handle_mode": "picker"
    }

    Unknown or invalid values are silently ignored and fall through to
    the next source. If you need to override per-request (e.g. for a
    specific signup campaign), append ?epds_handle_mode=picker to
    your /oauth/authorize URL.

    Operators: set EPDS_DEFAULT_HANDLE_MODE on the auth service
    to change the default handle-picker variant for clients that don't
    specify one in their client metadata. Accepted values are the same
    as those listed in the Client app developers section above
    (picker, random, picker-with-random). See .env.example for
    documentation.

Patch Changes

  • #58 905ad25 Thanks @aspiers! - Sign in faster from third-party apps that already know who you are.

    Affects: End users

    When you sign in to a third-party AT Protocol app (anything built
    on top of the Bluesky account system, for example) that already
    knows your handle or DID, ePDS now jumps straight to the "enter
    your sign-in code" step. Previously you would have been asked to
    retype your email address first, even though the app you were
    using had already identified you — that extra step is gone.

    This fixes two specific situations that didn't work before: apps
    that identified you by handle or DID rather than email, and apps
    that sent the identifier over a back channel rather than in the
    sign-in URL.

  • #58 905ad25 Thanks @aspiers! - Fail-fast validation of internal environment variables on the auth
    service.

    Affects: Operators

    A new requireInternalEnv() helper runs at auth service startup
    and reports exactly which required internal variables are missing
    or malformed, replacing cryptic downstream errors like
    TypeError: Failed to parse URL on the first request.

    Checks performed:

    • PDS_INTERNAL_URL — must be set and must begin with http://
      or https:// (matched case-insensitively). Trailing slashes are
      stripped automatically.
    • EPDS_INTERNAL_SECRET — must be set to any non-empty string.

    If you previously set PDS_INTERNAL_URL to a bare hostname like
    core.railway.internal or core:3000, the service will now
    refuse to start with this error:

    PDS_INTERNAL_URL is missing the http:// or https:// scheme: "core.railway.internal"
    

    Add the scheme and port explicitly. The canonical Docker Compose
    default (shown in .env.example) is http://core:3000; for
    Railway's private networking the equivalent is
    http://<service>.railway.internal:<PDS_PORT>, substituting
    whichever service name you gave your pds-core deployment and the
    PDS_PORT you configured on it. Railway's internal network uses
    plain HTTP on explicit ports, not HTTPS. This previously "worked"
    in the sense that the service started, but then failed on the
    first internal request; the new behaviour surfaces the
    misconfiguration immediately.

  • #58 905ad25 Thanks @aspiers! - Honour the generic PORT environment variable on both services, so
    Railway's automatic healthcheck succeeds without per-service
    configuration.

    Affects: Operators

    New port-resolution precedence (first set value wins):

    • auth service: AUTH_PORTPORT3001
    • pds-core: PDS_PORTPORT3000 (pds-core reads
      PDS_PORT; when PDS_PORT is unset, PORT is copied into it
      before @atproto/pds reads its environment)

    If you run ePDS on Docker Compose or another orchestrator where you
    set AUTH_PORT / PDS_PORT explicitly: no change — your existing
    settings take precedence over PORT.

    If you run ePDS on Railway (or any platform that injects PORT
    automatically): you can now remove service-specific AUTH_PORT /
    PDS_PORT overrides from your Railway variables. Each service
    will pick up Railway's injected PORT and healthchecks will bind
    correctly. Previously these services bound to their hardcoded
    defaults regardless of PORT, causing Railway healthchecks to
    fail.

@vercel

vercel Bot commented Apr 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
epds-demo Ready Ready Preview, Comment Apr 9, 2026 7:16pm

Request Review

@coveralls-official

coveralls-official Bot commented Apr 9, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 24208715153

Coverage remained the same at 29.583%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1638
Covered Lines: 517
Line Coverage: 31.56%
Relevant Branches: 931
Covered Branches: 243
Branch Coverage: 26.1%
Branches in Coverage %: Yes
Coverage Strength: 2.6 hits per line

💛 - Coveralls

The retroactive changesets added in #58 were all committed in the
same commit, so @changesets/changelog-github looked up that one
commit and used its PR (#58) and SHA on every generated entry in
the v0.2.0 release section. That's the generator behaving
correctly for its model (one changeset = one originating commit =
one originating PR) but it produces misleading "this change was
shipped in #58" refs when in reality each described feature
landed weeks earlier in a different PR.

Replace each bogus prefix with links to the real introducing
PR(s). Commit SHAs are dropped entirely because a feature that
spans multiple commits can't be meaningfully linked to a single
SHA, and the PR link already carries the useful context.

Future (non-retroactive) changesets won't hit this — they'll be
added in the same PR as the feature they describe, so the
generator's single-commit lookup resolves to the right PR
automatically. This fix is a one-off cleanup for the bootstrap
release.

PR → changeset mapping:
  #14 → Longer sign-in codes
  #13, #29, #33, #36 → Choose your own handle
  #3, #6 → Sign in faster from third-party apps
  #20, #23 → Fail-fast PDS_INTERNAL_URL validation
  #27 → Honour PORT env var
@aspiers
aspiers force-pushed the changeset-release/main branch from 40b93ac to 2bab91b Compare April 9, 2026 19:15
@sonarqubecloud

sonarqubecloud Bot commented Apr 9, 2026

Copy link
Copy Markdown

@aspiers aspiers changed the title chore: release chore: release v0.2.0 Apr 9, 2026
@aspiers aspiers changed the title chore: release v0.2.0 chore: prepare for release v0.2.0 Apr 9, 2026
@aspiers
aspiers merged commit 373d04f into main Apr 9, 2026
9 of 10 checks passed
@aspiers
aspiers deleted the changeset-release/main branch April 9, 2026 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant