@volter/twin-xidentity 0.1.1 → 0.1.2
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/dist/src/xidentity-server.js +14 -4
- package/package.json +3 -3
- package/src/xidentity-server.ts +14 -4
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
// • it serves the authorize page's own assets under the twin-namespaced `/_twin/assets/*`.
|
|
11
11
|
//
|
|
12
12
|
// It also tells the handler its OWN origin, so the consent form's action points BACK AT THE TWIN.
|
|
13
|
-
import { serveHttp } from '@volter/world-core';
|
|
13
|
+
import { isReadOnlyRequest, serveHttp, withRequestScopes } from '@volter/world-core';
|
|
14
14
|
import { CONSENT_CLIENT_CSS, CONSENT_CLIENT_JS, CONSENT_SCRIPT_PATH, CONSENT_STYLE_PATH } from "./xidentity-consent-ui.js";
|
|
15
|
+
import { oauthError } from "./xidentity-problems.js";
|
|
15
16
|
import { worldNow, statefulTwinManifest, twinPublicBase } from '@volter/world-core';
|
|
16
17
|
import { handleXIdentityTwinRequest } from "./xidentity-twin.js";
|
|
17
18
|
/**
|
|
@@ -28,8 +29,12 @@ import { handleXIdentityTwinRequest } from "./xidentity-twin.js";
|
|
|
28
29
|
* plane by `scripts/consent-clients.ts`) — no build and no disk read on the fetch path.
|
|
29
30
|
*/
|
|
30
31
|
export function createXIdentityTwinFetch(options = {}) {
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
// a read-only request (x-volter-read-only, a World's read token) is a request to a read-only twin: the
|
|
33
|
+
// authorize screen never signs anyone in or mints a code, no token is minted or revoked, GET
|
|
34
|
+
// /2/users/me is served without spending the app's rate window (D3), and the kernel refuses any write
|
|
35
|
+
// that slips past as X's own flat OAuth error
|
|
36
|
+
return withRequestScopes(async function xIdentityTwinFetch(request) {
|
|
37
|
+
const readOnly = (options.readOnly ?? false) || isReadOnlyRequest(request);
|
|
33
38
|
const url = new URL(request.url);
|
|
34
39
|
// GET /twin — the discovery manifest (education inside the twin).
|
|
35
40
|
if (request.method === 'GET' && url.pathname.replace(/\/+$/, '') === '/twin') {
|
|
@@ -67,7 +72,12 @@ export function createXIdentityTwinFetch(options = {}) {
|
|
|
67
72
|
}
|
|
68
73
|
out['content-type'] = out['content-type'] ?? 'application/json; charset=utf-8';
|
|
69
74
|
return new Response(JSON.stringify(res.body), { status: res.status, headers: out });
|
|
70
|
-
}
|
|
75
|
+
}, {
|
|
76
|
+
refuse: () => {
|
|
77
|
+
const refused = oauthError('temporarily_unavailable', 'this request is read-only', 405);
|
|
78
|
+
return Response.json(refused.body, { status: refused.status, headers: refused.headers });
|
|
79
|
+
},
|
|
80
|
+
});
|
|
71
81
|
}
|
|
72
82
|
export async function createXIdentityTwinServer(options) {
|
|
73
83
|
const server = await serveHttp({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/twin-xidentity",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Local X (Twitter) identity twin — the real x.com authorize screen, the full OAuth 2.0 authorization-code + PKCE round trip (token, refresh, revoke), and GET /2/users/me with X's real field/expansion/problem envelopes, so an unmodified X client completes sign-in-with-X against it. Built on @volter/world-core.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"twin",
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
"react-dom": "^19.2.7"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@volter/world-core": "2.0.
|
|
59
|
+
"@volter/world-core": "2.0.2"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@volter/world-core": "2.0.
|
|
62
|
+
"@volter/world-core": "2.0.2",
|
|
63
63
|
"@volter/world-tooling": "0.1.0",
|
|
64
64
|
"@xdevplatform/xdk": "^0.6.6",
|
|
65
65
|
"@types/bun": "^1.2.20",
|
package/src/xidentity-server.ts
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
// • it serves the authorize page's own assets under the twin-namespaced `/_twin/assets/*`.
|
|
11
11
|
//
|
|
12
12
|
// It also tells the handler its OWN origin, so the consent form's action points BACK AT THE TWIN.
|
|
13
|
-
import { serveHttp } from '@volter/world-core';
|
|
13
|
+
import { isReadOnlyRequest, serveHttp, withRequestScopes } from '@volter/world-core';
|
|
14
14
|
import { CONSENT_CLIENT_CSS, CONSENT_CLIENT_JS, CONSENT_SCRIPT_PATH, CONSENT_STYLE_PATH } from './xidentity-consent-ui.ts';
|
|
15
|
+
import { oauthError } from './xidentity-problems.ts';
|
|
15
16
|
import { worldNow, statefulTwinManifest, twinPublicBase } from '@volter/world-core';
|
|
16
17
|
import { handleXIdentityTwinRequest } from './xidentity-twin.ts';
|
|
17
18
|
|
|
@@ -35,8 +36,12 @@ export interface XIdentityTwinFetchOptions {
|
|
|
35
36
|
* plane by `scripts/consent-clients.ts`) — no build and no disk read on the fetch path.
|
|
36
37
|
*/
|
|
37
38
|
export function createXIdentityTwinFetch(options: XIdentityTwinFetchOptions = {}): (request: Request) => Promise<Response> {
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
// a read-only request (x-volter-read-only, a World's read token) is a request to a read-only twin: the
|
|
40
|
+
// authorize screen never signs anyone in or mints a code, no token is minted or revoked, GET
|
|
41
|
+
// /2/users/me is served without spending the app's rate window (D3), and the kernel refuses any write
|
|
42
|
+
// that slips past as X's own flat OAuth error
|
|
43
|
+
return withRequestScopes(async function xIdentityTwinFetch(request: Request): Promise<Response> {
|
|
44
|
+
const readOnly = (options.readOnly ?? false) || isReadOnlyRequest(request);
|
|
40
45
|
const url = new URL(request.url);
|
|
41
46
|
// GET /twin — the discovery manifest (education inside the twin).
|
|
42
47
|
if (request.method === 'GET' && url.pathname.replace(/\/+$/, '') === '/twin') {
|
|
@@ -77,7 +82,12 @@ export function createXIdentityTwinFetch(options: XIdentityTwinFetchOptions = {}
|
|
|
77
82
|
}
|
|
78
83
|
out['content-type'] = out['content-type'] ?? 'application/json; charset=utf-8';
|
|
79
84
|
return new Response(JSON.stringify(res.body), { status: res.status, headers: out });
|
|
80
|
-
}
|
|
85
|
+
}, {
|
|
86
|
+
refuse: () => {
|
|
87
|
+
const refused = oauthError('temporarily_unavailable', 'this request is read-only', 405);
|
|
88
|
+
return Response.json(refused.body, { status: refused.status, headers: refused.headers });
|
|
89
|
+
},
|
|
90
|
+
});
|
|
81
91
|
}
|
|
82
92
|
|
|
83
93
|
export async function createXIdentityTwinServer(options: { root?: string; port?: number; readOnly?: boolean }): Promise<{ port: number; stop: () => void }> {
|