epistery 2.0.4 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/.test.env +25 -0
  2. package/cli/epistery.mjs +9 -10
  3. package/dist/chains/registry.d.ts +2 -2
  4. package/dist/chains/registry.d.ts.map +1 -1
  5. package/dist/chains/registry.js +4 -4
  6. package/dist/chains/registry.js.map +1 -1
  7. package/dist/epistery.d.ts +1 -1
  8. package/dist/epistery.d.ts.map +1 -1
  9. package/dist/epistery.js +4 -4
  10. package/dist/epistery.js.map +1 -1
  11. package/dist/utils/CliWallet.d.ts +9 -5
  12. package/dist/utils/CliWallet.d.ts.map +1 -1
  13. package/dist/utils/CliWallet.js +18 -13
  14. package/dist/utils/CliWallet.js.map +1 -1
  15. package/dist/utils/Config.d.ts +104 -48
  16. package/dist/utils/Config.d.ts.map +1 -1
  17. package/dist/utils/Config.js +273 -116
  18. package/dist/utils/Config.js.map +1 -1
  19. package/dist/utils/Utils.d.ts +10 -2
  20. package/dist/utils/Utils.d.ts.map +1 -1
  21. package/dist/utils/Utils.js +18 -9
  22. package/dist/utils/Utils.js.map +1 -1
  23. package/docs/RivetSignerConfigAuthority.md +219 -0
  24. package/index.mjs +10 -9
  25. package/package.json +1 -1
  26. package/routes/auth.mjs +6 -6
  27. package/routes/domain.mjs +2 -2
  28. package/routes/fido.mjs +4 -4
  29. package/src/chains/registry.ts +4 -4
  30. package/src/epistery.ts +4 -4
  31. package/src/utils/CliWallet.ts +18 -13
  32. package/src/utils/Config.ts +313 -106
  33. package/src/utils/Utils.ts +19 -9
  34. package/test/config/.epistery/127.0.0.1/config.ini +15 -0
  35. package/test/config/.epistery/config.ini +14 -0
  36. package/test/config/.epistery/localhost/config.ini +16 -0
  37. package/test/config/.epistery/no-pending-claim.local/config.ini +15 -0
  38. package/test/config/.epistery/test-claim-1782325887560.local/config.ini +20 -0
  39. package/test/config/.epistery/test-idempotent-1782325887610.local/config.ini +20 -0
  40. package/test/config/.epistery/test-init-1782325888110.local/config.ini +16 -0
  41. package/test/routes/auth.test.ts +7 -3
  42. package/test/routes/identity.test.ts +0 -41
  43. package/test/routes/status.test.ts +5 -39
  44. package/test/setup.ts +9 -9
  45. package/test/utils.ts +9 -3
@@ -0,0 +1,20 @@
1
+ domain=test-idempotent-1782325887610.local
2
+ pending=true
3
+ challenge_token=4a6b22e1c5fbcc409a6a7b2818cc59adcdc209c9f17a830f6597a154112a393d
4
+ challenge_address=0xdcb8454e5ce6b911dba93c11ad530c61d2520d8e
5
+ challenge_created=2026-06-24T18:31:27.654Z
6
+ challenge_requester_ip=::ffff:127.0.0.1
7
+
8
+ [provider]
9
+ name=Polygon Amoy Testnet
10
+ chainId=80002
11
+ rpc=https://rpc-amoy.polygon.technology
12
+ nativeCurrencySymbol=POL
13
+ nativeCurrencyName=POL
14
+ nativeCurrencyDecimals=18
15
+
16
+ [wallet]
17
+ address=0x3088095FfBcfB4c5c41bF2013aaC445925D97053
18
+ mnemonic=jump youth pigeon erupt pigeon decorate pattern evil cage piece mean dawn
19
+ publicKey=0x04a6c3b50b9c644e9165c694b2aa999cf68dcb2c84d0d25944e77dbbce02efab7415726e7d73117df9923431238d1b2ba9041c1f0dc623102fd57d3bf80ec662ba
20
+ privateKey=0x759580a4cf6b6d0fe1903b59071186e2c6ecc6224d5c2852e76a031ea1218acf
@@ -0,0 +1,16 @@
1
+ domain=test-init-1782325888110.local
2
+ pending=true
3
+
4
+ [provider]
5
+ chainId=80002
6
+ name=Polygon Amoy Testnet
7
+ rpc=https://rpc-amoy.polygon.technology
8
+ nativeCurrencyName=POL
9
+ nativeCurrencySymbol=POL
10
+ nativeCurrencyDecimals=18
11
+
12
+ [wallet]
13
+ address=0x8b9190A997E5b79f680cD8bC075E4aF867264c69
14
+ mnemonic=copy blade pen core angry often manage tail vivid spice east allow
15
+ publicKey=0x04ad07e52a39f18eeb50423b73a6769d880520fbfecad2b12e01da538c0f114297b63be8b10ac1a873e21c4d0c6887986d96207007208d0bebcd798bc15f6e77cc
16
+ privateKey=0xce4633388ee13e3d516104f3f82b9a21bb8dc8e7c813c0261c70fd0b86b34d0a
@@ -119,14 +119,18 @@ describe('Auth Routes', () => {
119
119
  });
120
120
 
121
121
  describe('GET /auth/dns/claim', () => {
122
- it('should require address query parameter', async () => {
122
+ it('should error when no pending claim exists for the domain', async () => {
123
+ // localhost is regenerated clean by globalSetup (no pending claim), so the
124
+ // handler returns 400 from the no-pending guard before it ever reaches the
125
+ // missing-address check. (The 401 "Client address not found" path is only
126
+ // reachable once a pending claim exists for the domain.)
123
127
  const response = await testApp.supertest
124
128
  .get('/.well-known/epistery/auth/dns/claim')
125
129
  .set('Host', 'localhost')
126
- .expect(401);
130
+ .expect(400);
127
131
 
128
132
  expect(response.body.status).toBe('error');
129
- expect(response.body.message).toContain('address');
133
+ expect(response.body.message).toContain('pending');
130
134
  });
131
135
 
132
136
  it('should return error when no pending claim exists', async () => {
@@ -18,47 +18,6 @@ describe('Identity Routes', () => {
18
18
  // Cleanup if needed
19
19
  });
20
20
 
21
- describe('POST /identity/prepare-deploy', () => {
22
- it('should require client address', async () => {
23
- const response = await testApp.supertest
24
- .post('/.well-known/epistery/identity/prepare-deploy')
25
- .send({ domain: 'localhost' })
26
- .expect(400);
27
-
28
- expect(response.body.error).toContain('required fields');
29
- });
30
-
31
- it('should require domain', async () => {
32
- const response = await testApp.supertest
33
- .post('/.well-known/epistery/identity/prepare-deploy')
34
- .send({ clientAddress: TEST_WALLETS.client1.address })
35
- .expect(400);
36
-
37
- expect(response.body.error).toContain('required fields');
38
- });
39
-
40
- it('should prepare unsigned deployment transaction', async () => {
41
- if (!TEST_CONTRACT_ADDRESS) {
42
- console.log('Skipping: TEST_CONTRACT_ADDRESS not set');
43
- return;
44
- }
45
-
46
- const response = await testApp.supertest
47
- .post('/.well-known/epistery/identity/prepare-deploy')
48
- .send({
49
- clientAddress: TEST_WALLETS.client1.address,
50
- domain: 'localhost'
51
- })
52
- .timeout(60000);
53
-
54
- if (response.status === 200) {
55
- expect(response.body.unsignedTransaction).toBeDefined();
56
- } else {
57
- console.log('Prepare deploy failed:', response.body.error);
58
- }
59
- });
60
- });
61
-
62
21
  describe('POST /identity/prepare-add-rivet', () => {
63
22
  it('should require all fields', async () => {
64
23
  const response = await testApp.supertest
@@ -25,43 +25,6 @@ describe('Status Routes', () => {
25
25
  expect(response.body.server).toBeDefined();
26
26
  expect(response.body.server.walletAddress).toBeDefined();
27
27
  });
28
-
29
- it('should return HTML status page when Accept: text/html', async () => {
30
- const response = await testApp.supertest
31
- .get('/.well-known/epistery/')
32
- .set('Accept', 'text/html')
33
- .expect(200);
34
-
35
- expect(response.text).toContain('<!DOCTYPE html>');
36
- });
37
-
38
- it('should return HTML by default for browser requests', async () => {
39
- const response = await testApp.supertest
40
- .get('/.well-known/epistery/')
41
- .set('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')
42
- .expect(200);
43
-
44
- expect(response.text).toContain('<!DOCTYPE html>');
45
- });
46
- });
47
-
48
- describe('GET /status', () => {
49
- it('should return HTML status page', async () => {
50
- const response = await testApp.supertest
51
- .get('/.well-known/epistery/status')
52
- .expect(200);
53
-
54
- expect(response.text).toContain('<!DOCTYPE html>');
55
- });
56
-
57
- it('should include server domain in template', async () => {
58
- const response = await testApp.supertest
59
- .get('/.well-known/epistery/status')
60
- .set('Host', 'localhost:3000')
61
- .expect(200);
62
-
63
- expect(response.text).toContain('localhost');
64
- });
65
28
  });
66
29
 
67
30
  describe('GET /lib/:module', () => {
@@ -110,9 +73,12 @@ describe('Status Routes', () => {
110
73
  });
111
74
 
112
75
  describe('GET /artifacts/:contractFile', () => {
113
- it('should serve Agent.json contract artifact', async () => {
76
+ it('should serve IdentityContract.json contract artifact', async () => {
77
+ // Agent.sol was removed in the identity-only refactor (its artifact is
78
+ // kept only as reference). IdentityContract is the live contract the
79
+ // client fetches, so the artifact route is exercised against that.
114
80
  const response = await testApp.supertest
115
- .get('/.well-known/epistery/artifacts/Agent.json')
81
+ .get('/.well-known/epistery/artifacts/IdentityContract.json')
116
82
  .expect(200)
117
83
  .expect('Content-Type', /json/);
118
84
 
package/test/setup.ts CHANGED
@@ -38,14 +38,14 @@ export default async function globalSetup() {
38
38
  process.env.CHAIN_ID = String(TEST_PROVIDER.chainId);
39
39
  process.env.SERVER_DOMAIN = 'localhost';
40
40
 
41
- // 3. Generate test config files from environment variables
42
- const localhostDir = path.join(testConfigPath, 'localhost');
43
- if (!fs.existsSync(testConfigPath)) {
44
- fs.mkdirSync(testConfigPath, { recursive: true });
45
- }
46
- if (!fs.existsSync(localhostDir)) {
47
- fs.mkdirSync(localhostDir, { recursive: true });
48
- }
41
+ // 3. Generate test config files from environment variables.
42
+ // Config reads HOME/.epistery (configDir = join(HOME, '.epistery')), so the
43
+ // fixtures must live under .epistery — NOT directly under HOME. (They used to
44
+ // be written one level too high, so Config never saw them and auto-seeded
45
+ // defaults + random wallets.)
46
+ const episteryDir = path.join(testConfigPath, '.epistery');
47
+ const localhostDir = path.join(episteryDir, 'localhost');
48
+ fs.mkdirSync(localhostDir, { recursive: true });
49
49
 
50
50
  // Write root config
51
51
  const rootConfig = `[profile]
@@ -63,7 +63,7 @@ nativeCurrencyDecimals=${TEST_PROVIDER.nativeCurrencyDecimals}
63
63
  [cli]
64
64
  default_domain=localhost
65
65
  `;
66
- fs.writeFileSync(path.join(testConfigPath, 'config.ini'), rootConfig);
66
+ fs.writeFileSync(path.join(episteryDir, 'config.ini'), rootConfig);
67
67
 
68
68
  // Write localhost domain config
69
69
  const localhostConfig = `domain=localhost
package/test/utils.ts CHANGED
@@ -180,11 +180,17 @@ export async function createBotAuthHeader(wallet: ethers.Wallet): Promise<string
180
180
  }
181
181
 
182
182
  /**
183
- * Create a session cookie for authenticated requests
183
+ * Create a session cookie for authenticated requests.
184
+ *
185
+ * Matches the three-fact session shape the auth middleware reads
186
+ * (index.mjs: s.signerAddress / s.contractAddress / s.publicKey). The old field
187
+ * name `rivetAddress` predated the identity-vocabulary migration and was silently
188
+ * ignored by the middleware (no signerAddress → unauthenticated).
184
189
  */
185
- export function createSessionCookie(rivetAddress: string, publicKey?: string): string {
190
+ export function createSessionCookie(signerAddress: string, publicKey?: string, contractAddress?: string | null): string {
186
191
  const sessionData = {
187
- rivetAddress,
192
+ signerAddress,
193
+ contractAddress: contractAddress || null,
188
194
  publicKey: publicKey || '',
189
195
  authenticated: true,
190
196
  timestamp: new Date().toISOString()