epistery 2.0.3 → 2.1.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.
- package/.test.env +25 -0
- package/cli/epistery.mjs +9 -10
- package/client/wallet.js +30 -7
- package/client/witness.js +29 -12
- package/dist/chains/registry.d.ts +2 -2
- package/dist/chains/registry.d.ts.map +1 -1
- package/dist/chains/registry.js +4 -4
- package/dist/chains/registry.js.map +1 -1
- package/dist/epistery.d.ts +1 -1
- package/dist/epistery.d.ts.map +1 -1
- package/dist/epistery.js +4 -4
- package/dist/epistery.js.map +1 -1
- package/dist/utils/CliWallet.d.ts +9 -5
- package/dist/utils/CliWallet.d.ts.map +1 -1
- package/dist/utils/CliWallet.js +18 -13
- package/dist/utils/CliWallet.js.map +1 -1
- package/dist/utils/Config.d.ts +101 -48
- package/dist/utils/Config.d.ts.map +1 -1
- package/dist/utils/Config.js +257 -116
- package/dist/utils/Config.js.map +1 -1
- package/dist/utils/Utils.d.ts +10 -2
- package/dist/utils/Utils.d.ts.map +1 -1
- package/dist/utils/Utils.js +18 -9
- package/dist/utils/Utils.js.map +1 -1
- package/docs/RivetSignerConfigAuthority.md +219 -0
- package/index.mjs +10 -9
- package/package.json +1 -1
- package/routes/auth.mjs +6 -6
- package/routes/domain.mjs +2 -2
- package/routes/fido.mjs +4 -4
- package/src/chains/registry.ts +4 -4
- package/src/epistery.ts +4 -4
- package/src/utils/CliWallet.ts +18 -13
- package/src/utils/Config.ts +289 -106
- package/src/utils/Utils.ts +19 -9
- package/test/config/.epistery/127.0.0.1/config.ini +15 -0
- package/test/config/.epistery/config.ini +14 -0
- package/test/config/.epistery/localhost/config.ini +16 -0
- package/test/config/.epistery/no-pending-claim.local/config.ini +15 -0
- package/test/config/.epistery/test-claim-1782325887560.local/config.ini +20 -0
- package/test/config/.epistery/test-idempotent-1782325887610.local/config.ini +20 -0
- package/test/config/.epistery/test-init-1782325888110.local/config.ini +16 -0
- package/test/routes/auth.test.ts +7 -3
- package/test/routes/identity.test.ts +0 -41
- package/test/routes/status.test.ts +5 -39
- package/test/setup.ts +9 -9
- package/test/utils.ts +9 -3
|
@@ -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
|
package/test/routes/auth.test.ts
CHANGED
|
@@ -119,14 +119,18 @@ describe('Auth Routes', () => {
|
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
describe('GET /auth/dns/claim', () => {
|
|
122
|
-
it('should
|
|
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(
|
|
130
|
+
.expect(400);
|
|
127
131
|
|
|
128
132
|
expect(response.body.status).toBe('error');
|
|
129
|
-
expect(response.body.message).toContain('
|
|
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
|
|
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/
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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(
|
|
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(
|
|
190
|
+
export function createSessionCookie(signerAddress: string, publicKey?: string, contractAddress?: string | null): string {
|
|
186
191
|
const sessionData = {
|
|
187
|
-
|
|
192
|
+
signerAddress,
|
|
193
|
+
contractAddress: contractAddress || null,
|
|
188
194
|
publicKey: publicKey || '',
|
|
189
195
|
authenticated: true,
|
|
190
196
|
timestamp: new Date().toISOString()
|