|
| 1 | +# OISY Signer Domain Migration |
| 2 | + |
| 3 | +This document describes the multi-milestone plan to decouple the OISY signer from the main wallet domain, enabling independent versioning and lifecycle management for the signer. |
| 4 | + |
| 5 | +## Background |
| 6 | + |
| 7 | +OISY currently serves the signer UI at `oisy.com/sign`. Dapps using `@dfinity/oisy-wallet-signer` (agent-js v4) open this URL to interact with users' wallets via ICRC-21/25/27/49 standards. |
| 8 | + |
| 9 | +A separate signer origin also helps with **Progressive Web Apps**. If both OISY and a dapp are installed as PWAs, the signer standards do not reliably support communication between two installed PWAs. Moving the signer to its own domain lets a dapp open the signer in a normal browser window while users can still install OISY as a PWA. |
| 10 | + |
| 11 | +With the upcoming migration to agent-js v5, the signer protocol changes in a **backwards-incompatible** way. To give dapp developers a smooth transition, the signer is deployed to dedicated subdomains: |
| 12 | + |
| 13 | +- **`signer.oisy.com`** -- the forward-looking signer URL (for dapps on v5, and currently also v4 during the transition) |
| 14 | +- **`legacy-signer.oisy.com`** -- the legacy signer URL (for dapps that remain on v4) |
| 15 | + |
| 16 | +**Compatibility note:** A dapp on agent-js v5 _can_ talk to a v4 signer, but **not** the other way around. This means dapps can start using `signer.oisy.com` immediately, even while the signer itself is still on v4. |
| 17 | + |
| 18 | +## Domain Structure |
| 19 | + |
| 20 | +Production hostnames: |
| 21 | + |
| 22 | +| Role | Domain | |
| 23 | +| ------------- | ------------------------ | |
| 24 | +| Main wallet | `oisy.com` | |
| 25 | +| Signer | `signer.oisy.com` | |
| 26 | +| Legacy signer | `legacy-signer.oisy.com` | |
| 27 | + |
| 28 | +Staging and beta use the same layout under internal hostnames. Those URLs are maintained for the team in `scripts/domains.json` and per-environment `.env` files and are intentionally not listed here. |
| 29 | + |
| 30 | +Each production hostname maps to a **separate IC asset canister**. This is required because: |
| 31 | + |
| 32 | +1. Different canisters will serve different code versions (starting from Milestone 2) |
| 33 | +2. Custom domains on the IC are bound to specific canisters |
| 34 | + |
| 35 | +## Identity Derivation |
| 36 | + |
| 37 | +All signer domains derive their Internet Identity from the **same canonical origin** as the main wallet for that environment, so users see the same accounts everywhere. The exact value is `AUTH_DERIVATION_ORIGIN` / `VITE_AUTH_DERIVATION_ORIGIN` in the matching `.env` file (production uses `https://oisy.com`). |
| 38 | + |
| 39 | +For this to work, the signer domains must be listed in the main frontend canister's `/.well-known/ii-alternative-origins`. This is configured via the `VITE_AUTH_ALTERNATIVE_ORIGINS` env var in each environment's `.env` file. |
| 40 | + |
| 41 | +## Build and Deploy |
| 42 | + |
| 43 | +The signer frontends use the **same codebase** as the main wallet. The build target is controlled by the `OISY_SIGNER_TARGET` environment variable. |
| 44 | + |
| 45 | +### Build and deploy commands |
| 46 | + |
| 47 | +Each signer canister has a `build` command in `dfx.json` that automatically sets `OISY_SIGNER_TARGET`. Local, staging, and beta deploys typically use `dfx deploy` with the right network and wallet (no manual `OISY_SIGNER_TARGET` needed): |
| 48 | + |
| 49 | +```bash |
| 50 | +# Deploy the main frontend (no signer target, uses package.json version) |
| 51 | +dfx deploy frontend --network <network> |
| 52 | + |
| 53 | +# Deploy the signer frontend (automatically sets OISY_SIGNER_TARGET=signer) |
| 54 | +dfx deploy signer_frontend --network <network> |
| 55 | + |
| 56 | +# Deploy the legacy signer frontend (automatically sets OISY_SIGNER_TARGET=legacy_signer) |
| 57 | +dfx deploy legacy_signer_frontend --network <network> |
| 58 | +``` |
| 59 | + |
| 60 | +**Production (IC):** Upgrades to `frontend`, `signer_frontend`, and `legacy_signer_frontend` on the IC network go through the same **Orbit-controlled** workflow as the main wallet (station approval, `dfx-oisy` / `dfx-orbit` requests), not a one-off `dfx deploy` from a developer laptop. See [Deployment → IC](HACKING.md#ic) in HACKING.md. |
| 61 | + |
| 62 | +The `OISY_SIGNER_TARGET` env var is baked into each canister's `build` command in `dfx.json`, so deployers never need to set it manually. The canister name determines the build target. |
| 63 | + |
| 64 | +### What `OISY_SIGNER_TARGET` controls |
| 65 | + |
| 66 | +When set, this env var affects the build in several ways: |
| 67 | + |
| 68 | +| Aspect | Default (unset) | `signer` | `legacy_signer` | |
| 69 | +| ------------------------ | ------------------- | ---------------------------- | -------------------------------- | |
| 70 | +| `VITE_OISY_DOMAIN` | `https://oisy.com` | `https://signer.oisy.com` | `https://legacy-signer.oisy.com` | |
| 71 | +| `VITE_APP_VERSION` | from `package.json` | from `signer-versions.json` | from `signer-versions.json` | |
| 72 | +| `.well-known/ic-domains` | `oisy.com` | `signer.oisy.com` | `legacy-signer.oisy.com` | |
| 73 | +| `AUTH_DERIVATION_ORIGIN` | (varies) | Canonical origin \* | Canonical origin \* | |
| 74 | +| Plausible domain | `oisy.com` | `signer.oisy.com` | `legacy-signer.oisy.com` | |
| 75 | +| SvelteKit reroute | Normal routing | All routes -> `/sign` | All routes -> `/sign` | |
| 76 | +| `ii-alternative-origins` | Lists alt origins | Lists alt origins (from env) | Lists alt origins (from env) | |
| 77 | + |
| 78 | +\* Canonical origin per environment: see `AUTH_DERIVATION_ORIGIN` and [Identity Derivation](#identity-derivation). |
| 79 | + |
| 80 | +### Versioning |
| 81 | + |
| 82 | +The signer frontends have their own version numbers, independent of the main wallet's `package.json` version. These are stored in `signer-versions.json`: |
| 83 | + |
| 84 | +```json |
| 85 | +{ |
| 86 | + "signer_frontend": "1.0.0", |
| 87 | + "legacy_signer_frontend": "1.0.0" |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +When `OISY_SIGNER_TARGET` is set, both `vite.utils.ts` and `svelte.config.js` read the version from this file instead of `package.json`. This allows each signer to be released independently -- particularly important when `legacy-signer` is frozen at v4 while `signer` advances with v5. |
| 92 | + |
| 93 | +### Canister definitions |
| 94 | + |
| 95 | +The new canisters are defined in `dfx.json` as `signer_frontend` and `legacy_signer_frontend`, and their IDs are in `canister_ids.json`. Domain-to-URL mappings live in `scripts/domains.json`. |
| 96 | + |
| 97 | +## Analytics |
| 98 | + |
| 99 | +Each signer domain reports to Plausible under its own domain name. This means you can see traffic to each site independently in the Plausible dashboard. |
| 100 | + |
| 101 | +## Migration Milestones |
| 102 | + |
| 103 | +### Milestone 1: Dual-domain rollout (current) |
| 104 | + |
| 105 | +- Deploy the current v4 signer code to `signer.oisy.com` and `legacy-signer.oisy.com` |
| 106 | +- `oisy.com/sign` continues to work unchanged |
| 107 | +- All three URLs serve the same signer code |
| 108 | +- Communicate to dapp developers: |
| 109 | + - If already on agent-js v5 (or planning to migrate): use `signer.oisy.com` |
| 110 | + - If staying on agent-js v4 for now: use `legacy-signer.oisy.com` |
| 111 | +- Monitor usage via Plausible analytics |
| 112 | +- **Important:** `legacy-signer.oisy.com` will only receive hotfixes. Full support ends after a grace period (target: Q3 2026) |
| 113 | + |
| 114 | +### Milestone 2: Deploy v5 signer |
| 115 | + |
| 116 | +- Upgrade the OISY signer to agent-js v5 |
| 117 | +- Deploy the v5 signer to `signer.oisy.com` and `oisy.com` |
| 118 | +- Keep the v4 signer on `legacy-signer.oisy.com` (frozen at the last v4 version) |
| 119 | +- Dapps still on v4 that did not switch to `legacy-signer.oisy.com` will see errors on `oisy.com/sign` |
| 120 | + - Detect v4 dapps and show a user-friendly error message |
| 121 | + - Send a Plausible event to identify affected dapps |
| 122 | +- Track remaining usage of `oisy.com/sign` from v4 dapps |
| 123 | + |
| 124 | +### Milestone 3: Legacy signer sunset |
| 125 | + |
| 126 | +- All dapp projects should have migrated to v5 or moved to `legacy-signer.oisy.com` |
| 127 | +- Turn off `legacy-signer.oisy.com` |
| 128 | +- Remove legacy signer canister and domain configuration |
| 129 | + |
| 130 | +## Key Files |
| 131 | + |
| 132 | +| File | Purpose | |
| 133 | +| ------------------------------------------------- | ------------------------------------------------------ | |
| 134 | +| `signer-versions.json` | Independent version numbers for signer frontends | |
| 135 | +| `scripts/domains.json` | Domain-to-URL mapping per canister + network | |
| 136 | +| `dfx.json` | Canister definitions and network config | |
| 137 | +| `canister_ids.json` | Canister IDs per network | |
| 138 | +| `vite.utils.ts` | Build-time domain resolution + globals | |
| 139 | +| `scripts/build.utils.mjs` | Post-process domain resolution | |
| 140 | +| `src/frontend/src/hooks.ts` | SvelteKit reroute hook (signer -> `/sign`) | |
| 141 | +| `src/frontend/src/lib/constants/app.constants.ts` | `SIGNER_TARGET`, `IS_SIGNER_DOMAIN`, derivation origin | |
| 142 | +| `src/frontend/src/env/plausible.env.ts` | Plausible domain per signer target | |
| 143 | +| `.env.production` / `.env.staging` / `.env.beta` | `VITE_AUTH_ALTERNATIVE_ORIGINS` with signer domains | |
0 commit comments