Skip to content

Commit 381b595

Browse files
AntonioVentiliigithub-actions[bot]Copilot
authored
chore(doc): Add Signer Domains documentation (#12284)
# Motivation Useful to have some guide about Signer Domains. --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent d25b59c commit 381b595

2 files changed

Lines changed: 148 additions & 0 deletions

File tree

HACKING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ This document lists a couple of useful information for development and deploymen
55
## Table of content
66

77
- [Deployment](#deployment)
8+
- [Signer Domains](#signer-domains)
89
- [Internationalization](#internationalization)
910
- [Faucets](#faucets)
1011
- [Testing](#testing)
@@ -80,6 +81,10 @@ scripts/docker-build
8081
dfx-orbit request canister install backend --mode upgrade --wasm out/backend.wasm.gz --arg-file out/backend.args.did
8182
```
8283

84+
### Signer Domains
85+
86+
The OISY signer is deployed to dedicated production subdomains (`signer.oisy.com`, `legacy-signer.oisy.com`) with their own canisters and versioning. Production IC deploys for those asset canisters use the **same Orbit-controlled process** as the main wallet `frontend` (see [IC](#ic) above: Docker image build, then `dfx-oisy request deploy`, with verification via `dfx-orbit` where applicable). For architecture, build targets, identity derivation, and the migration plan, see [SIGNER_DOMAINS.md](SIGNER_DOMAINS.md).
87+
8388
## Internationalization
8489

8590
Translations are handled in JSON file - for example [en.json](src/frontend/src/lib/i18n/en.json). We selected this format because they can easily be edited by third parties even without developer skills.

SIGNER_DOMAINS.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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

Comments
 (0)