@betterportal/tunnels 1.0.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/README.md +76 -0
- package/SPEC.md +524 -0
- package/lib/.bsb/clients/service-tunnel-client-api.d.ts +133 -0
- package/lib/.bsb/clients/service-tunnel-client-api.d.ts.map +1 -0
- package/lib/.bsb/clients/service-tunnel-client-api.js +102 -0
- package/lib/.bsb/clients/service-tunnel-client-api.js.map +1 -0
- package/lib/.bsb/clients/service-tunnel-web.d.ts +43 -0
- package/lib/.bsb/clients/service-tunnel-web.d.ts.map +1 -0
- package/lib/.bsb/clients/service-tunnel-web.js +47 -0
- package/lib/.bsb/clients/service-tunnel-web.js.map +1 -0
- package/lib/auth.d.ts +12 -0
- package/lib/auth.d.ts.map +1 -0
- package/lib/auth.js +59 -0
- package/lib/auth.js.map +1 -0
- package/lib/cli.d.ts +2 -0
- package/lib/cli.d.ts.map +1 -0
- package/lib/cli.js +295 -0
- package/lib/cli.js.map +1 -0
- package/lib/plugins/service-betterportal/.bp-generated/registry.d.ts +3 -0
- package/lib/plugins/service-betterportal/.bp-generated/registry.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/.bp-generated/registry.js +127 -0
- package/lib/plugins/service-betterportal/.bp-generated/registry.js.map +1 -0
- package/lib/plugins/service-betterportal/assets/brand/bettertunnels-horizontal-light.svg +18 -0
- package/lib/plugins/service-betterportal/assets/brand/bettertunnels-square-dark-1024x1024.png +0 -0
- package/lib/plugins/service-betterportal/assets/brand/favicon.svg +12 -0
- package/lib/plugins/service-betterportal/betterportal-logo.png +0 -0
- package/lib/plugins/service-betterportal/bp-routes/cli-auth/verify/_theme.bootstrap1/index.d.ts +5 -0
- package/lib/plugins/service-betterportal/bp-routes/cli-auth/verify/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/cli-auth/verify/_theme.bootstrap1/index.js +6 -0
- package/lib/plugins/service-betterportal/bp-routes/cli-auth/verify/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/cli-auth/verify/index.d.ts +25 -0
- package/lib/plugins/service-betterportal/bp-routes/cli-auth/verify/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/cli-auth/verify/index.js +59 -0
- package/lib/plugins/service-betterportal/bp-routes/cli-auth/verify/index.js.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/dashboard/_theme.bootstrap1/index.d.ts +5 -0
- package/lib/plugins/service-betterportal/bp-routes/dashboard/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/dashboard/_theme.bootstrap1/index.js +22 -0
- package/lib/plugins/service-betterportal/bp-routes/dashboard/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/dashboard/index.d.ts +40 -0
- package/lib/plugins/service-betterportal/bp-routes/dashboard/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/dashboard/index.js +57 -0
- package/lib/plugins/service-betterportal/bp-routes/dashboard/index.js.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/downloads/_theme.bootstrap1/index.d.ts +5 -0
- package/lib/plugins/service-betterportal/bp-routes/downloads/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/downloads/_theme.bootstrap1/index.js +5 -0
- package/lib/plugins/service-betterportal/bp-routes/downloads/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/downloads/index.d.ts +30 -0
- package/lib/plugins/service-betterportal/bp-routes/downloads/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/downloads/index.js +45 -0
- package/lib/plugins/service-betterportal/bp-routes/downloads/index.js.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/landing/_theme.bootstrap1/index.d.ts +5 -0
- package/lib/plugins/service-betterportal/bp-routes/landing/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/landing/_theme.bootstrap1/index.js +5 -0
- package/lib/plugins/service-betterportal/bp-routes/landing/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/landing/index.d.ts +40 -0
- package/lib/plugins/service-betterportal/bp-routes/landing/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/landing/index.js +63 -0
- package/lib/plugins/service-betterportal/bp-routes/landing/index.js.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/tunnels/_theme.bootstrap1/index.d.ts +5 -0
- package/lib/plugins/service-betterportal/bp-routes/tunnels/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/tunnels/_theme.bootstrap1/index.js +5 -0
- package/lib/plugins/service-betterportal/bp-routes/tunnels/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/tunnels/index.d.ts +44 -0
- package/lib/plugins/service-betterportal/bp-routes/tunnels/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/bp-routes/tunnels/index.js +59 -0
- package/lib/plugins/service-betterportal/bp-routes/tunnels/index.js.map +1 -0
- package/lib/plugins/service-betterportal/brand-assets.d.ts +7 -0
- package/lib/plugins/service-betterportal/brand-assets.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/brand-assets.js +24 -0
- package/lib/plugins/service-betterportal/brand-assets.js.map +1 -0
- package/lib/plugins/service-betterportal/index.d.ts +57 -0
- package/lib/plugins/service-betterportal/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal/index.js +108 -0
- package/lib/plugins/service-betterportal/index.js.map +1 -0
- package/lib/plugins/service-tunnel-client-api/ids.d.ts +6 -0
- package/lib/plugins/service-tunnel-client-api/ids.d.ts.map +1 -0
- package/lib/plugins/service-tunnel-client-api/ids.js +17 -0
- package/lib/plugins/service-tunnel-client-api/ids.js.map +1 -0
- package/lib/plugins/service-tunnel-client-api/index.d.ts +158 -0
- package/lib/plugins/service-tunnel-client-api/index.d.ts.map +1 -0
- package/lib/plugins/service-tunnel-client-api/index.js +591 -0
- package/lib/plugins/service-tunnel-client-api/index.js.map +1 -0
- package/lib/plugins/service-tunnel-client-api/registry.d.ts +36 -0
- package/lib/plugins/service-tunnel-client-api/registry.d.ts.map +1 -0
- package/lib/plugins/service-tunnel-client-api/registry.js +14 -0
- package/lib/plugins/service-tunnel-client-api/registry.js.map +1 -0
- package/lib/plugins/service-tunnel-client-api/schemas.d.ts +66 -0
- package/lib/plugins/service-tunnel-client-api/schemas.d.ts.map +1 -0
- package/lib/plugins/service-tunnel-client-api/schemas.js +56 -0
- package/lib/plugins/service-tunnel-client-api/schemas.js.map +1 -0
- package/lib/plugins/service-tunnel-web/http.d.ts +4 -0
- package/lib/plugins/service-tunnel-web/http.d.ts.map +1 -0
- package/lib/plugins/service-tunnel-web/http.js +119 -0
- package/lib/plugins/service-tunnel-web/http.js.map +1 -0
- package/lib/plugins/service-tunnel-web/index.d.ts +79 -0
- package/lib/plugins/service-tunnel-web/index.d.ts.map +1 -0
- package/lib/plugins/service-tunnel-web/index.js +278 -0
- package/lib/plugins/service-tunnel-web/index.js.map +1 -0
- package/lib/plugins/service-tunnel-web/verification.d.ts +27 -0
- package/lib/plugins/service-tunnel-web/verification.d.ts.map +1 -0
- package/lib/plugins/service-tunnel-web/verification.js +209 -0
- package/lib/plugins/service-tunnel-web/verification.js.map +1 -0
- package/lib/prisma.d.ts +6 -0
- package/lib/prisma.d.ts.map +1 -0
- package/lib/prisma.js +10 -0
- package/lib/prisma.js.map +1 -0
- package/lib/schemas/service-betterportal.json +109 -0
- package/lib/schemas/service-tunnel-client-api.json +300 -0
- package/lib/schemas/service-tunnel-web.json +140 -0
- package/package.json +60 -0
- package/prisma/migrations/0001_init/migration.sql +63 -0
- package/prisma/migrations/0002_account_plan/migration.sql +6 -0
- package/prisma/migrations/0003_tunnel_owner_server/migration.sql +1 -0
- package/prisma/migrations/20260701000000_add_client_auth/migration.sql +46 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +141 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pluginName": "service-betterportal",
|
|
3
|
+
"events": {},
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"configSchema": {
|
|
6
|
+
"anyvaliVersion": "1.0",
|
|
7
|
+
"schemaVersion": "1.1",
|
|
8
|
+
"root": {
|
|
9
|
+
"kind": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
"host": {
|
|
12
|
+
"kind": "string",
|
|
13
|
+
"minLength": 1,
|
|
14
|
+
"default": "0.0.0.0"
|
|
15
|
+
},
|
|
16
|
+
"port": {
|
|
17
|
+
"kind": "int",
|
|
18
|
+
"min": 1,
|
|
19
|
+
"default": 8083
|
|
20
|
+
},
|
|
21
|
+
"betterportal": {
|
|
22
|
+
"kind": "optional",
|
|
23
|
+
"inner": {
|
|
24
|
+
"kind": "object",
|
|
25
|
+
"properties": {
|
|
26
|
+
"bpConfigPath": {
|
|
27
|
+
"kind": "optional",
|
|
28
|
+
"inner": {
|
|
29
|
+
"kind": "string",
|
|
30
|
+
"minLength": 1
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"configApiToken": {
|
|
34
|
+
"kind": "optional",
|
|
35
|
+
"inner": {
|
|
36
|
+
"kind": "string",
|
|
37
|
+
"minLength": 1
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"configEncryptionKey": {
|
|
41
|
+
"kind": "optional",
|
|
42
|
+
"inner": {
|
|
43
|
+
"kind": "string",
|
|
44
|
+
"minLength": 16
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"controlPlaneUrl": {
|
|
48
|
+
"kind": "optional",
|
|
49
|
+
"inner": {
|
|
50
|
+
"kind": "string",
|
|
51
|
+
"minLength": 1
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"serviceApiKey": {
|
|
55
|
+
"kind": "optional",
|
|
56
|
+
"inner": {
|
|
57
|
+
"kind": "string",
|
|
58
|
+
"minLength": 1
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"bootstrapStatePath": {
|
|
62
|
+
"kind": "string",
|
|
63
|
+
"minLength": 1,
|
|
64
|
+
"default": "./.bp-bootstrap/state.enc"
|
|
65
|
+
},
|
|
66
|
+
"scopedConfigCachePath": {
|
|
67
|
+
"kind": "string",
|
|
68
|
+
"minLength": 1,
|
|
69
|
+
"default": "./.bp-sync-cache/scoped.json"
|
|
70
|
+
},
|
|
71
|
+
"trustedProxyHeaders": {
|
|
72
|
+
"kind": "bool",
|
|
73
|
+
"default": false
|
|
74
|
+
},
|
|
75
|
+
"cfProxy": {
|
|
76
|
+
"kind": "bool",
|
|
77
|
+
"default": false
|
|
78
|
+
},
|
|
79
|
+
"trustedProxyIps": {
|
|
80
|
+
"kind": "array",
|
|
81
|
+
"items": {
|
|
82
|
+
"kind": "string",
|
|
83
|
+
"minLength": 1
|
|
84
|
+
},
|
|
85
|
+
"default": []
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"required": [
|
|
89
|
+
"bootstrapStatePath",
|
|
90
|
+
"scopedConfigCachePath",
|
|
91
|
+
"trustedProxyHeaders",
|
|
92
|
+
"cfProxy",
|
|
93
|
+
"trustedProxyIps"
|
|
94
|
+
],
|
|
95
|
+
"unknownKeys": "strip"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"required": [
|
|
100
|
+
"host",
|
|
101
|
+
"port"
|
|
102
|
+
],
|
|
103
|
+
"unknownKeys": "strip"
|
|
104
|
+
},
|
|
105
|
+
"definitions": {},
|
|
106
|
+
"extensions": {}
|
|
107
|
+
},
|
|
108
|
+
"pluginType": "service"
|
|
109
|
+
}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pluginName": "service-tunnel-client-api",
|
|
3
|
+
"events": {
|
|
4
|
+
"ws.toOrigin": {
|
|
5
|
+
"type": "fire-and-forget",
|
|
6
|
+
"category": "onEvents",
|
|
7
|
+
"description": "Relay a public websocket frame to the connected tunnel client",
|
|
8
|
+
"inputSchema": {
|
|
9
|
+
"anyvaliVersion": "1.0",
|
|
10
|
+
"schemaVersion": "1.1",
|
|
11
|
+
"root": {
|
|
12
|
+
"kind": "object",
|
|
13
|
+
"properties": {
|
|
14
|
+
"publicServerId": {
|
|
15
|
+
"kind": "string"
|
|
16
|
+
},
|
|
17
|
+
"publicSocketId": {
|
|
18
|
+
"kind": "string"
|
|
19
|
+
},
|
|
20
|
+
"hostname": {
|
|
21
|
+
"kind": "string"
|
|
22
|
+
},
|
|
23
|
+
"path": {
|
|
24
|
+
"kind": "string"
|
|
25
|
+
},
|
|
26
|
+
"frameType": {
|
|
27
|
+
"kind": "string"
|
|
28
|
+
},
|
|
29
|
+
"event": {
|
|
30
|
+
"kind": "optional",
|
|
31
|
+
"inner": {
|
|
32
|
+
"kind": "string"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"body": {
|
|
36
|
+
"kind": "optional",
|
|
37
|
+
"inner": {
|
|
38
|
+
"kind": "string"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"required": [
|
|
43
|
+
"publicServerId",
|
|
44
|
+
"publicSocketId",
|
|
45
|
+
"hostname",
|
|
46
|
+
"path",
|
|
47
|
+
"frameType"
|
|
48
|
+
],
|
|
49
|
+
"unknownKeys": "strip"
|
|
50
|
+
},
|
|
51
|
+
"definitions": {},
|
|
52
|
+
"extensions": {
|
|
53
|
+
"bsb": {
|
|
54
|
+
"description": "Public websocket frame to origin"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"outputSchema": null
|
|
59
|
+
},
|
|
60
|
+
"proxy.metrics": {
|
|
61
|
+
"type": "fire-and-forget",
|
|
62
|
+
"category": "onEvents",
|
|
63
|
+
"description": "Send final proxy request timings to the connected tunnel client",
|
|
64
|
+
"inputSchema": {
|
|
65
|
+
"anyvaliVersion": "1.0",
|
|
66
|
+
"schemaVersion": "1.1",
|
|
67
|
+
"root": {
|
|
68
|
+
"kind": "object",
|
|
69
|
+
"properties": {
|
|
70
|
+
"hostname": {
|
|
71
|
+
"kind": "string"
|
|
72
|
+
},
|
|
73
|
+
"requestId": {
|
|
74
|
+
"kind": "string"
|
|
75
|
+
},
|
|
76
|
+
"totalMs": {
|
|
77
|
+
"kind": "number"
|
|
78
|
+
},
|
|
79
|
+
"clientApiRoundtripMs": {
|
|
80
|
+
"kind": "optional",
|
|
81
|
+
"inner": {
|
|
82
|
+
"kind": "number"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"cliOverheadMs": {
|
|
86
|
+
"kind": "optional",
|
|
87
|
+
"inner": {
|
|
88
|
+
"kind": "number"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"originMs": {
|
|
92
|
+
"kind": "optional",
|
|
93
|
+
"inner": {
|
|
94
|
+
"kind": "number"
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"internalServerMs": {
|
|
98
|
+
"kind": "optional",
|
|
99
|
+
"inner": {
|
|
100
|
+
"kind": "number"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"required": [
|
|
105
|
+
"hostname",
|
|
106
|
+
"requestId",
|
|
107
|
+
"totalMs"
|
|
108
|
+
],
|
|
109
|
+
"unknownKeys": "strip"
|
|
110
|
+
},
|
|
111
|
+
"definitions": {},
|
|
112
|
+
"extensions": {
|
|
113
|
+
"bsb": {
|
|
114
|
+
"description": "Proxy request metrics"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"outputSchema": null
|
|
119
|
+
},
|
|
120
|
+
"proxy.request": {
|
|
121
|
+
"type": "returnable",
|
|
122
|
+
"category": "onReturnableEvents",
|
|
123
|
+
"description": "Proxy an HTTP request through a connected tunnel client",
|
|
124
|
+
"defaultTimeout": 60,
|
|
125
|
+
"inputSchema": {
|
|
126
|
+
"anyvaliVersion": "1.0",
|
|
127
|
+
"schemaVersion": "1.1",
|
|
128
|
+
"root": {
|
|
129
|
+
"kind": "object",
|
|
130
|
+
"properties": {
|
|
131
|
+
"hostname": {
|
|
132
|
+
"kind": "string"
|
|
133
|
+
},
|
|
134
|
+
"method": {
|
|
135
|
+
"kind": "string"
|
|
136
|
+
},
|
|
137
|
+
"path": {
|
|
138
|
+
"kind": "string"
|
|
139
|
+
},
|
|
140
|
+
"headers": {
|
|
141
|
+
"kind": "record",
|
|
142
|
+
"valueSchema": {
|
|
143
|
+
"kind": "string"
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"body": {
|
|
147
|
+
"kind": "optional",
|
|
148
|
+
"inner": {
|
|
149
|
+
"kind": "string"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"webStartedAt": {
|
|
153
|
+
"kind": "number"
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
"required": [
|
|
157
|
+
"hostname",
|
|
158
|
+
"method",
|
|
159
|
+
"path",
|
|
160
|
+
"headers",
|
|
161
|
+
"webStartedAt"
|
|
162
|
+
],
|
|
163
|
+
"unknownKeys": "strip"
|
|
164
|
+
},
|
|
165
|
+
"definitions": {},
|
|
166
|
+
"extensions": {
|
|
167
|
+
"bsb": {
|
|
168
|
+
"description": "Proxy request"
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
"outputSchema": {
|
|
173
|
+
"anyvaliVersion": "1.0",
|
|
174
|
+
"schemaVersion": "1.1",
|
|
175
|
+
"root": {
|
|
176
|
+
"kind": "object",
|
|
177
|
+
"properties": {
|
|
178
|
+
"requestId": {
|
|
179
|
+
"kind": "string"
|
|
180
|
+
},
|
|
181
|
+
"ownerServerId": {
|
|
182
|
+
"kind": "string"
|
|
183
|
+
},
|
|
184
|
+
"status": {
|
|
185
|
+
"kind": "number"
|
|
186
|
+
},
|
|
187
|
+
"headers": {
|
|
188
|
+
"kind": "record",
|
|
189
|
+
"valueSchema": {
|
|
190
|
+
"kind": "string"
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
"body": {
|
|
194
|
+
"kind": "string"
|
|
195
|
+
},
|
|
196
|
+
"webStartedAt": {
|
|
197
|
+
"kind": "number"
|
|
198
|
+
},
|
|
199
|
+
"clientApiRoundtripMs": {
|
|
200
|
+
"kind": "number"
|
|
201
|
+
},
|
|
202
|
+
"cliOverheadMs": {
|
|
203
|
+
"kind": "optional",
|
|
204
|
+
"inner": {
|
|
205
|
+
"kind": "number"
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"originMs": {
|
|
209
|
+
"kind": "optional",
|
|
210
|
+
"inner": {
|
|
211
|
+
"kind": "number"
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
"required": [
|
|
216
|
+
"requestId",
|
|
217
|
+
"ownerServerId",
|
|
218
|
+
"status",
|
|
219
|
+
"headers",
|
|
220
|
+
"body",
|
|
221
|
+
"webStartedAt",
|
|
222
|
+
"clientApiRoundtripMs"
|
|
223
|
+
],
|
|
224
|
+
"unknownKeys": "strip"
|
|
225
|
+
},
|
|
226
|
+
"definitions": {},
|
|
227
|
+
"extensions": {
|
|
228
|
+
"bsb": {
|
|
229
|
+
"description": "Proxy response"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
"version": "1.0.0",
|
|
236
|
+
"configSchema": {
|
|
237
|
+
"anyvaliVersion": "1.0",
|
|
238
|
+
"schemaVersion": "1.1",
|
|
239
|
+
"root": {
|
|
240
|
+
"kind": "object",
|
|
241
|
+
"properties": {
|
|
242
|
+
"port": {
|
|
243
|
+
"kind": "number",
|
|
244
|
+
"default": 8081,
|
|
245
|
+
"metadata": {
|
|
246
|
+
"description": "Client API listener port"
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
"domain": {
|
|
250
|
+
"kind": "string",
|
|
251
|
+
"default": "tunnels.betterportal.dev",
|
|
252
|
+
"metadata": {
|
|
253
|
+
"description": "Default public tunnel domain"
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
"publicUrl": {
|
|
257
|
+
"kind": "string",
|
|
258
|
+
"default": "https://tunnels.betterportal.dev",
|
|
259
|
+
"metadata": {
|
|
260
|
+
"description": "Public base URL"
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
"authAppBaseUrl": {
|
|
264
|
+
"kind": "string",
|
|
265
|
+
"default": "https://betterportal.cloud",
|
|
266
|
+
"metadata": {
|
|
267
|
+
"description": "BetterPortal app URL used for CLI auth"
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
"authVerifyPath": {
|
|
271
|
+
"kind": "string",
|
|
272
|
+
"default": "/cli-auth/verify",
|
|
273
|
+
"metadata": {
|
|
274
|
+
"description": "BetterPortal CLI auth verify route"
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
"required": [
|
|
279
|
+
"port",
|
|
280
|
+
"domain",
|
|
281
|
+
"publicUrl",
|
|
282
|
+
"authAppBaseUrl",
|
|
283
|
+
"authVerifyPath"
|
|
284
|
+
],
|
|
285
|
+
"unknownKeys": "strip",
|
|
286
|
+
"metadata": {
|
|
287
|
+
"description": "service-tunnel-client-api config"
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
"definitions": {},
|
|
291
|
+
"extensions": {}
|
|
292
|
+
},
|
|
293
|
+
"pluginType": "service",
|
|
294
|
+
"dependencies": [
|
|
295
|
+
{
|
|
296
|
+
"id": "_/service-tunnel-web.js",
|
|
297
|
+
"version": "1.0.0"
|
|
298
|
+
}
|
|
299
|
+
]
|
|
300
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pluginName": "service-tunnel-web",
|
|
3
|
+
"events": {
|
|
4
|
+
"ws.fromOrigin": {
|
|
5
|
+
"type": "fire-and-forget",
|
|
6
|
+
"category": "onEvents",
|
|
7
|
+
"description": "Relay an origin websocket frame to the public websocket",
|
|
8
|
+
"inputSchema": {
|
|
9
|
+
"anyvaliVersion": "1.0",
|
|
10
|
+
"schemaVersion": "1.1",
|
|
11
|
+
"root": {
|
|
12
|
+
"kind": "object",
|
|
13
|
+
"properties": {
|
|
14
|
+
"publicSocketId": {
|
|
15
|
+
"kind": "string"
|
|
16
|
+
},
|
|
17
|
+
"frameType": {
|
|
18
|
+
"kind": "string"
|
|
19
|
+
},
|
|
20
|
+
"event": {
|
|
21
|
+
"kind": "optional",
|
|
22
|
+
"inner": {
|
|
23
|
+
"kind": "string"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"body": {
|
|
27
|
+
"kind": "optional",
|
|
28
|
+
"inner": {
|
|
29
|
+
"kind": "string"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"required": [
|
|
34
|
+
"publicSocketId",
|
|
35
|
+
"frameType"
|
|
36
|
+
],
|
|
37
|
+
"unknownKeys": "strip"
|
|
38
|
+
},
|
|
39
|
+
"definitions": {},
|
|
40
|
+
"extensions": {
|
|
41
|
+
"bsb": {
|
|
42
|
+
"description": "Origin websocket frame to public client"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"outputSchema": null
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"version": "1.0.0",
|
|
50
|
+
"configSchema": {
|
|
51
|
+
"anyvaliVersion": "1.0",
|
|
52
|
+
"schemaVersion": "1.1",
|
|
53
|
+
"root": {
|
|
54
|
+
"kind": "object",
|
|
55
|
+
"properties": {
|
|
56
|
+
"port": {
|
|
57
|
+
"kind": "number",
|
|
58
|
+
"default": 8080,
|
|
59
|
+
"metadata": {
|
|
60
|
+
"description": "Public web listener port"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"domain": {
|
|
64
|
+
"kind": "string",
|
|
65
|
+
"default": "tunnels.betterportal.dev",
|
|
66
|
+
"metadata": {
|
|
67
|
+
"description": "Tunnel root domain"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"verificationHost": {
|
|
71
|
+
"kind": "string",
|
|
72
|
+
"default": "verify.tunnels.betterportal.dev",
|
|
73
|
+
"metadata": {
|
|
74
|
+
"description": "Verification host"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"cookieSecret": {
|
|
78
|
+
"kind": "string",
|
|
79
|
+
"default": "dev-cookie-secret",
|
|
80
|
+
"metadata": {
|
|
81
|
+
"description": "Signed verification cookie secret"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"turnstileSiteKey": {
|
|
85
|
+
"kind": "optional",
|
|
86
|
+
"inner": {
|
|
87
|
+
"kind": "string"
|
|
88
|
+
},
|
|
89
|
+
"metadata": {
|
|
90
|
+
"description": "Cloudflare Turnstile site key"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"turnstileSecretKey": {
|
|
94
|
+
"kind": "optional",
|
|
95
|
+
"inner": {
|
|
96
|
+
"kind": "string"
|
|
97
|
+
},
|
|
98
|
+
"metadata": {
|
|
99
|
+
"description": "Cloudflare Turnstile secret key"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"maxHeaderBytes": {
|
|
103
|
+
"kind": "number",
|
|
104
|
+
"default": 32768,
|
|
105
|
+
"metadata": {
|
|
106
|
+
"description": "Maximum accepted request header bytes"
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"maxBodyBytes": {
|
|
110
|
+
"kind": "number",
|
|
111
|
+
"default": 2097152,
|
|
112
|
+
"metadata": {
|
|
113
|
+
"description": "Maximum accepted request body bytes"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"required": [
|
|
118
|
+
"port",
|
|
119
|
+
"domain",
|
|
120
|
+
"verificationHost",
|
|
121
|
+
"cookieSecret",
|
|
122
|
+
"maxHeaderBytes",
|
|
123
|
+
"maxBodyBytes"
|
|
124
|
+
],
|
|
125
|
+
"unknownKeys": "strip",
|
|
126
|
+
"metadata": {
|
|
127
|
+
"description": "service-tunnel-web config"
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"definitions": {},
|
|
131
|
+
"extensions": {}
|
|
132
|
+
},
|
|
133
|
+
"pluginType": "service",
|
|
134
|
+
"dependencies": [
|
|
135
|
+
{
|
|
136
|
+
"id": "_/service-tunnel-client-api.js",
|
|
137
|
+
"version": "1.0.0"
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@betterportal/tunnels",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "(AGPL-3.0-only OR Commercial)",
|
|
6
|
+
"files": [
|
|
7
|
+
"lib/",
|
|
8
|
+
"prisma/",
|
|
9
|
+
"README.md",
|
|
10
|
+
"SPEC.md",
|
|
11
|
+
"package.json"
|
|
12
|
+
],
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "bsb-plugin-cli build",
|
|
18
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
19
|
+
"dev": "bsb-plugin-cli dev",
|
|
20
|
+
"start": "bsb-plugin-cli start",
|
|
21
|
+
"cli": "tsx src/cli.ts",
|
|
22
|
+
"bp-codegen": "bp-codegen",
|
|
23
|
+
"prisma:generate": "prisma generate",
|
|
24
|
+
"prisma:migrate": "prisma migrate dev",
|
|
25
|
+
"test": "node --import tsx --test tests/*.test.ts",
|
|
26
|
+
"check": "npm run build && npm test"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@betterportal/framework": "^10.0.0",
|
|
30
|
+
"@betterportal/plugin-bsb": "^10.0.0",
|
|
31
|
+
"@bsb/base": "^9.6.41",
|
|
32
|
+
"@bsb/config-vault": "^9.6.47",
|
|
33
|
+
"@prisma/adapter-pg": "^7.8.0",
|
|
34
|
+
"@prisma/client": "^7.8.0",
|
|
35
|
+
"anyvali": "^1.0.6",
|
|
36
|
+
"dotenv": "^17.2.3",
|
|
37
|
+
"h3": "^2.0.1-rc.22",
|
|
38
|
+
"jsx-htmx": "^4.0.0-beta2",
|
|
39
|
+
"pg": "^8.22.0",
|
|
40
|
+
"ws": "^8.18.3"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^24.10.1",
|
|
44
|
+
"@types/ws": "^8.18.1",
|
|
45
|
+
"prisma": "^7.8.0",
|
|
46
|
+
"tsx": "^4.21.0",
|
|
47
|
+
"typescript": "^5.9.3"
|
|
48
|
+
},
|
|
49
|
+
"bsb": {
|
|
50
|
+
"hooks": {
|
|
51
|
+
"afterSchemas": "bp-codegen",
|
|
52
|
+
"beforeCompile": "prisma:generate"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"betterportal": {
|
|
56
|
+
"routes": [
|
|
57
|
+
"src/plugins/service-betterportal/bp-routes/"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
CREATE TYPE "TunnelStatus" AS ENUM ('created', 'active', 'draining', 'disconnected', 'expired', 'closed');
|
|
2
|
+
|
|
3
|
+
CREATE TABLE "Account" (
|
|
4
|
+
"id" TEXT PRIMARY KEY,
|
|
5
|
+
"email" TEXT UNIQUE,
|
|
6
|
+
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
CREATE TABLE "ClientSession" (
|
|
10
|
+
"id" TEXT PRIMARY KEY,
|
|
11
|
+
"accountId" TEXT,
|
|
12
|
+
"ipHash" TEXT,
|
|
13
|
+
"userAgent" TEXT,
|
|
14
|
+
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
15
|
+
"expiresAt" TIMESTAMPTZ
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
CREATE TABLE "Tunnel" (
|
|
19
|
+
"id" TEXT PRIMARY KEY,
|
|
20
|
+
"accountId" TEXT,
|
|
21
|
+
"sessionId" TEXT NOT NULL,
|
|
22
|
+
"subdomain" TEXT NOT NULL UNIQUE,
|
|
23
|
+
"targetHost" TEXT NOT NULL,
|
|
24
|
+
"targetPort" INTEGER NOT NULL,
|
|
25
|
+
"authenticated" BOOLEAN NOT NULL DEFAULT false,
|
|
26
|
+
"status" "TunnelStatus" NOT NULL DEFAULT 'created',
|
|
27
|
+
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
28
|
+
"expiresAt" TIMESTAMPTZ NOT NULL,
|
|
29
|
+
CONSTRAINT "Tunnel_accountId_fkey" FOREIGN KEY ("accountId") REFERENCES "Account"("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
|
30
|
+
CONSTRAINT "Tunnel_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "ClientSession"("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
CREATE TABLE "VisitorValidation" (
|
|
34
|
+
"id" TEXT PRIMARY KEY,
|
|
35
|
+
"tunnelId" TEXT NOT NULL,
|
|
36
|
+
"visitorIpHash" TEXT NOT NULL,
|
|
37
|
+
"userAgentHash" TEXT NOT NULL,
|
|
38
|
+
"validationCookieHash" TEXT NOT NULL,
|
|
39
|
+
"validatedAt" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
40
|
+
"expiresAt" TIMESTAMPTZ NOT NULL,
|
|
41
|
+
CONSTRAINT "VisitorValidation_tunnelId_fkey" FOREIGN KEY ("tunnelId") REFERENCES "Tunnel"("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE TABLE "UsageCounter" (
|
|
45
|
+
"tunnelId" TEXT PRIMARY KEY,
|
|
46
|
+
"requests" INTEGER NOT NULL DEFAULT 0,
|
|
47
|
+
"bytesIn" BIGINT NOT NULL DEFAULT 0,
|
|
48
|
+
"bytesOut" BIGINT NOT NULL DEFAULT 0,
|
|
49
|
+
"updatedAt" TIMESTAMPTZ NOT NULL,
|
|
50
|
+
CONSTRAINT "UsageCounter_tunnelId_fkey" FOREIGN KEY ("tunnelId") REFERENCES "Tunnel"("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
CREATE TABLE "AuditEvent" (
|
|
54
|
+
"id" TEXT PRIMARY KEY,
|
|
55
|
+
"event" TEXT NOT NULL,
|
|
56
|
+
"subjectId" TEXT,
|
|
57
|
+
"data" JSONB,
|
|
58
|
+
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE INDEX "Tunnel_sessionId_idx" ON "Tunnel"("sessionId");
|
|
62
|
+
CREATE INDEX "Tunnel_expiresAt_idx" ON "Tunnel"("expiresAt");
|
|
63
|
+
CREATE INDEX "VisitorValidation_tunnelId_visitorIpHash_userAgentHash_idx" ON "VisitorValidation"("tunnelId", "visitorIpHash", "userAgentHash");
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
CREATE TYPE "AccountPlan" AS ENUM ('anonymous', 'free', 'paid', 'admin');
|
|
2
|
+
|
|
3
|
+
ALTER TABLE "Account"
|
|
4
|
+
ADD COLUMN "plan" "AccountPlan" NOT NULL DEFAULT 'anonymous',
|
|
5
|
+
ADD COLUMN "verificationBypass" BOOLEAN NOT NULL DEFAULT false,
|
|
6
|
+
ADD COLUMN "ipVerification" BOOLEAN NOT NULL DEFAULT false;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE "Tunnel" ADD COLUMN "ownerServerId" TEXT;
|