@yourrealm/sdk 0.0.0-alpha.1378.ce03c8dc
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/LICENSE-EXCEPTION +26 -0
- package/README.md +34 -0
- package/dist/chunk-3R6KEFOI.js +22 -0
- package/dist/chunk-67BDAMYX.js +376 -0
- package/dist/chunk-AITGS27R.js +139 -0
- package/dist/chunk-CMAEHQ4F.js +6 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-O3UIK34B.js +1430 -0
- package/dist/chunk-VHTUSZUX.js +176 -0
- package/dist/cli.js +9006 -0
- package/dist/docker.js +54 -0
- package/dist/index.js +1053 -0
- package/dist/ingress.js +436 -0
- package/dist/jsx-runtime.js +2 -0
- package/dist/preact.js +22 -0
- package/dist/service-url.js +11 -0
- package/dist/services.js +213 -0
- package/dist/test.js +5069 -0
- package/dist/ui.js +254 -0
- package/dist/worker-protocol.js +89 -0
- package/package.json +112 -0
- package/src/app-icon.ts +74 -0
- package/src/apply.ts +52 -0
- package/src/bundle-ui.ts +211 -0
- package/src/bundle.ts +546 -0
- package/src/cli/build-dev-landing.ts +84 -0
- package/src/cli/build-install-panel.ts +90 -0
- package/src/cli/build-runtime.ts +133 -0
- package/src/cli/build.ts +63 -0
- package/src/cli/dev.ts +107 -0
- package/src/cli/down.ts +60 -0
- package/src/cli/main.ts +56 -0
- package/src/cli/test.ts +61 -0
- package/src/cli/validate.ts +37 -0
- package/src/compile.ts +100 -0
- package/src/create-app.ts +982 -0
- package/src/deep-merge.ts +33 -0
- package/src/dev/fixture.ts +48 -0
- package/src/dev/install-handler.ts +383 -0
- package/src/dev/server.ts +968 -0
- package/src/dev/stack.ts +108 -0
- package/src/dev/state.ts +159 -0
- package/src/docker.ts +96 -0
- package/src/errors.ts +61 -0
- package/src/factory.ts +481 -0
- package/src/garage.ts +56 -0
- package/src/generator/hash.ts +6 -0
- package/src/generator/resolve-refs.ts +207 -0
- package/src/grants-builder.ts +100 -0
- package/src/grants.ts +260 -0
- package/src/home-api.ts +172 -0
- package/src/home-cookie.ts +10 -0
- package/src/home-registry.ts +120 -0
- package/src/home.ts +187 -0
- package/src/host-registry.ts +143 -0
- package/src/http-header.ts +20 -0
- package/src/identifiers.ts +49 -0
- package/src/index.ts +66 -0
- package/src/info.ts +64 -0
- package/src/ini.ts +50 -0
- package/src/json.ts +14 -0
- package/src/jsx-runtime/index.ts +5 -0
- package/src/keys.ts +29 -0
- package/src/mysql.ts +56 -0
- package/src/pack-build.ts +108 -0
- package/src/pack.ts +115 -0
- package/src/peer-registry.ts +121 -0
- package/src/peer-world.ts +117 -0
- package/src/permission-meta.ts +116 -0
- package/src/permissions.ts +108 -0
- package/src/pkg-root.ts +34 -0
- package/src/postgres.ts +79 -0
- package/src/preact/index.ts +27 -0
- package/src/redis.ts +43 -0
- package/src/ref.ts +271 -0
- package/src/remote-registry.ts +33 -0
- package/src/required-host-kinds.ts +110 -0
- package/src/resolve-context.ts +111 -0
- package/src/resolve.ts +471 -0
- package/src/runtime/docker/compose/compose-schema.ts +118 -0
- package/src/runtime/docker/compose/convert-to-docker-compose.ts +278 -0
- package/src/runtime/docker/compose/default-hardening.ts +21 -0
- package/src/runtime/docker/compose/effects.ts +107 -0
- package/src/runtime/docker/compose/index.ts +17 -0
- package/src/runtime/docker/compose/labels.ts +39 -0
- package/src/runtime/docker/compose/types.ts +78 -0
- package/src/runtime/docker/home-proxy-server/index.ts +177 -0
- package/src/runtime/docker/home-proxy-server/protocol.ts +53 -0
- package/src/runtime/docker/ingress/build-config.ts +819 -0
- package/src/runtime/docker/ingress/index.ts +16 -0
- package/src/runtime/docker/ingress/types.ts +182 -0
- package/src/runtime/docker/log-frames.ts +121 -0
- package/src/runtime/docker/logs-server/index.ts +366 -0
- package/src/runtime/docker/spawn-server/context-key.ts +82 -0
- package/src/runtime/docker/spawn-server/index.ts +492 -0
- package/src/runtime/docker/spawn-server/protocol.ts +70 -0
- package/src/runtime/docker/spawn-server/spec.ts +122 -0
- package/src/runtime/docker/stats-server/disks.ts +161 -0
- package/src/runtime/docker/stats-server/index.ts +322 -0
- package/src/runtime/home-client/index.ts +71 -0
- package/src/runtime/log-line.ts +24 -0
- package/src/runtime/logs-client/index.ts +175 -0
- package/src/runtime/spawn-client/index.ts +93 -0
- package/src/runtime/spawn-client/kaniko.ts +79 -0
- package/src/runtime/stats-client/index.ts +65 -0
- package/src/runtime/stats-sample.ts +95 -0
- package/src/safe-json.ts +37 -0
- package/src/sandbox.ts +1209 -0
- package/src/schema/build-apps.ts +38 -0
- package/src/schema/home.ts +217 -0
- package/src/schema/host.ts +792 -0
- package/src/schema/inputs.ts +26 -0
- package/src/schema/nodes.ts +75 -0
- package/src/schema/peer.ts +400 -0
- package/src/schema/public-domain.ts +116 -0
- package/src/schema/remote.ts +74 -0
- package/src/security.ts +594 -0
- package/src/serialize.ts +21 -0
- package/src/service-definition.ts +284 -0
- package/src/service-url.ts +64 -0
- package/src/service.ts +39 -0
- package/src/services/index.ts +5 -0
- package/src/shared.ts +65 -0
- package/src/speculative-silo.ts +96 -0
- package/src/stable-secret.ts +14 -0
- package/src/surfaces.ts +264 -0
- package/src/tailwind-bin.ts +56 -0
- package/src/test/boot.ts +192 -0
- package/src/test/compile.ts +501 -0
- package/src/test/describe.ts +117 -0
- package/src/test/index.ts +11 -0
- package/src/test/ingress-fixture.ts +37 -0
- package/src/test/types.ts +318 -0
- package/src/trusted-headers.ts +79 -0
- package/src/types.ts +126 -0
- package/src/ui/components/aside.tsx +96 -0
- package/src/ui/components/badge.tsx +42 -0
- package/src/ui/components/button.tsx +59 -0
- package/src/ui/components/card.tsx +106 -0
- package/src/ui/components/checkbox.tsx +37 -0
- package/src/ui/components/code-block.tsx +29 -0
- package/src/ui/components/combobox.tsx +119 -0
- package/src/ui/components/config-field.tsx +284 -0
- package/src/ui/components/dialog.tsx +137 -0
- package/src/ui/components/domain-editor.tsx +317 -0
- package/src/ui/components/domain-list.ts +205 -0
- package/src/ui/components/dropdown-menu.tsx +73 -0
- package/src/ui/components/empty-state.tsx +51 -0
- package/src/ui/components/highlight.ts +59 -0
- package/src/ui/components/icons.tsx +101 -0
- package/src/ui/components/image-posture.tsx +85 -0
- package/src/ui/components/input.tsx +28 -0
- package/src/ui/components/label.tsx +16 -0
- package/src/ui/components/line-chart.tsx +113 -0
- package/src/ui/components/page.tsx +39 -0
- package/src/ui/components/permission-row.tsx +262 -0
- package/src/ui/components/permission-section.tsx +51 -0
- package/src/ui/components/pie-chart.tsx +245 -0
- package/src/ui/components/schema-block.tsx +60 -0
- package/src/ui/components/separator.tsx +42 -0
- package/src/ui/components/sheet.tsx +130 -0
- package/src/ui/components/sidebar.tsx +650 -0
- package/src/ui/components/silo-picker.tsx +510 -0
- package/src/ui/components/skeleton.tsx +13 -0
- package/src/ui/components/sonner.tsx +33 -0
- package/src/ui/components/switch.tsx +58 -0
- package/src/ui/components/table-view.ts +219 -0
- package/src/ui/components/table.tsx +506 -0
- package/src/ui/components/tabs.tsx +59 -0
- package/src/ui/components/timeago.tsx +84 -0
- package/src/ui/components/tooltip.tsx +56 -0
- package/src/ui/components.json +21 -0
- package/src/ui/dev/dev-shell.tsx +145 -0
- package/src/ui/home/home-grid.tsx +177 -0
- package/src/ui/hooks/use-mobile.ts +19 -0
- package/src/ui/index.ts +189 -0
- package/src/ui/install/adapter.ts +193 -0
- package/src/ui/install/deploy-targets-picker.tsx +185 -0
- package/src/ui/install/install-app-panel.tsx +912 -0
- package/src/ui/install/install-error.tsx +62 -0
- package/src/ui/install/perms-inactive.ts +50 -0
- package/src/ui/install/required-fields.ts +37 -0
- package/src/ui/install/tabs-form.tsx +557 -0
- package/src/ui/tokens.css +279 -0
- package/src/ui/utils.ts +78 -0
- package/src/ui-error.ts +139 -0
- package/src/ui-runtime/dev-landing-entry.tsx +258 -0
- package/src/ui-runtime/index.ts +83 -0
- package/src/ui-runtime/install-entry.tsx +119 -0
- package/src/ui-runtime/mount.ts +367 -0
- package/src/ui-runtime/runtime.css +56 -0
- package/src/ui-surface.ts +451 -0
- package/src/valkey.ts +43 -0
- package/src/worker/extract-tar.ts +125 -0
- package/src/worker/identity.ts +183 -0
- package/src/worker/index.ts +16 -0
- package/src/worker/public-ip.ts +92 -0
- package/src/worker/queue.ts +54 -0
- package/src/worker/reconcile.ts +127 -0
- package/src/worker/start-worker.ts +227 -0
- package/src/worker/ui-proxy.ts +335 -0
- package/src/worker/uplink.ts +523 -0
- package/src/worker/validate.ts +34 -0
- package/src/worker/verify-relay.ts +102 -0
- package/src/worker-protocol/app-dirs.ts +94 -0
- package/src/worker-protocol/home-proxy-paths.ts +76 -0
- package/src/worker-protocol/index.ts +55 -0
- package/src/worker-protocol/ingress.ts +166 -0
- package/src/worker-protocol/logs-socket-path.ts +50 -0
- package/src/worker-protocol/networks.ts +39 -0
- package/src/worker-protocol/node-version.ts +70 -0
- package/src/worker-protocol/silo-paths.ts +114 -0
- package/src/worker-protocol/spawn-paths.ts +165 -0
- package/src/worker-protocol/stats-socket-path.ts +40 -0
- package/src/worker-protocol/update-files.ts +77 -0
- package/src/worker-protocol/uplink/constants.ts +86 -0
- package/src/worker-protocol/uplink/errors.ts +61 -0
- package/src/worker-protocol/uplink/frame.ts +114 -0
- package/src/worker-protocol/uplink/identity.ts +40 -0
- package/src/worker-protocol/uplink/index.ts +63 -0
- package/src/worker-protocol/uplink/methods.ts +462 -0
- package/src/worker-protocol/uplink/mux.ts +646 -0
- package/src/worker-protocol/uplink/protocol.ts +11 -0
- package/src/worker-protocol/uplink/rpc.ts +309 -0
- package/src/worker-protocol/uplink/session.ts +540 -0
- package/src/worker-protocol/uplink/test-support.ts +188 -0
- package/src/worker-protocol/worker-mount.ts +27 -0
- package/src/worker-protocol/worker-state.ts +190 -0
- package/src/xml.ts +49 -0
- package/src/yaml.ts +15 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// The shared contract for build-recipe data: Home resolves it (resolve.ts
|
|
2
|
+
// validates each service's `build`, peer.ts's `peers.buildApps` emits
|
|
3
|
+
// `BuildAppEntry[]`), Forge parses `/etc/forge/apps.json` against
|
|
4
|
+
// `buildAppsSchema`. A dependency-free leaf (only `zod`) so the Forge bundle
|
|
5
|
+
// pulls just this, not the peer/factory machinery, and so it stays off the
|
|
6
|
+
// author-facing root barrel — a Forge↔Home contract, not author surface.
|
|
7
|
+
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Build-from-source recipe, mutually exclusive with `image` on a service.
|
|
12
|
+
* Recipe only — no repo/branch (the build service's binding lives in Forge).
|
|
13
|
+
* Structurally mirrors the `BuildRecipe` author interface in
|
|
14
|
+
* service-definition.ts; the resolver normalizes `build: true` to `{}` here.
|
|
15
|
+
*/
|
|
16
|
+
export const buildRecipeSchema = z
|
|
17
|
+
.object({
|
|
18
|
+
dockerfile: z.string().optional(),
|
|
19
|
+
buildArgs: z.record(z.string(), z.string()).optional(),
|
|
20
|
+
context: z.string().optional(),
|
|
21
|
+
})
|
|
22
|
+
.strict();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* One build target's resolved recipe, keyed by `(appId, service)`. Home's
|
|
26
|
+
* `peers.buildApps` peerable emits one entry per build-from-source service
|
|
27
|
+
* across apps; Forge looks the recipe up by `(appId, service)` when a push
|
|
28
|
+
* triggers a build.
|
|
29
|
+
*/
|
|
30
|
+
export const buildAppsSchema = z.array(
|
|
31
|
+
z.object({
|
|
32
|
+
appId: z.string(),
|
|
33
|
+
service: z.string(),
|
|
34
|
+
recipe: buildRecipeSchema,
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export type BuildAppEntry = z.infer<typeof buildAppsSchema>[number];
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// home.* permission factories + per-kind Home-side mechanics.
|
|
2
|
+
//
|
|
3
|
+
// Each factory is built via `homeable(...)` (the local binding of
|
|
4
|
+
// `makeHomeable(basePermission)`), which calls basePermission AND tags the
|
|
5
|
+
// kind's hooks (iterateUses / toValue / grantSchema) so the home registry
|
|
6
|
+
// derived in grants.ts can dispatch through them. Adding a home kind is one
|
|
7
|
+
// declaration here.
|
|
8
|
+
//
|
|
9
|
+
// QuickJS-safe: only `z` + pure constants at module load (the `WorkerHostPath`
|
|
10
|
+
// import is type-only). This module loads inside QuickJS during realm.ts eval,
|
|
11
|
+
// so it must touch no `Deno` or Web globals at load.
|
|
12
|
+
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
import type { WorkerHostPath } from "../worker-protocol/logs-socket-path.ts";
|
|
15
|
+
import type { WorkerMount } from "../worker-protocol/worker-mount.ts";
|
|
16
|
+
import { homeProxyMount } from "../worker-protocol/home-proxy-paths.ts";
|
|
17
|
+
import { basePermission } from "../factory.ts";
|
|
18
|
+
import { makeHomeable } from "../home-registry.ts";
|
|
19
|
+
import {
|
|
20
|
+
publicDomainValueSchema,
|
|
21
|
+
type PublicDomain,
|
|
22
|
+
type PublicDomainGrantData,
|
|
23
|
+
type PublicDomainValue,
|
|
24
|
+
} from "./public-domain.ts";
|
|
25
|
+
|
|
26
|
+
const homeable = makeHomeable(basePermission);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Closed set of control-plane capability scopes `home.apiAccess` can grant.
|
|
30
|
+
* Each names *what the app may do*, not a specific endpoint, so one scope can
|
|
31
|
+
* back several routes. An unknown scope is rejected at grant time (lands in
|
|
32
|
+
* `sanitizeGrants`'s `rejected` bucket).
|
|
33
|
+
*
|
|
34
|
+
* - `builder` — the build-service control plane: re-pin a `build:` app to a
|
|
35
|
+
* pushed digest (setImage), manage a template's preview children, and upsert
|
|
36
|
+
* a pull credential. The three always travel together — a builder wants all
|
|
37
|
+
* of them, nobody wants a subset — so they're one scope. Home enforces it
|
|
38
|
+
* **singleton**: at most one app per Home may hold `builder`, so there is
|
|
39
|
+
* exactly one builder and no sibling app can re-pin or shadow another app's
|
|
40
|
+
* images. The per-endpoint fences (build-only, lineage, self-or-lineage)
|
|
41
|
+
* still apply on top of the scope.
|
|
42
|
+
* - `whoami` — read your own identity + deployment facts (appId, granted
|
|
43
|
+
* scopes, worker slug, base domain). Low-privilege and **unlimited** (any
|
|
44
|
+
* number of apps may hold it), so `home.apiAccess` stays a general primitive
|
|
45
|
+
* rather than becoming builder-only once `builder` is singleton.
|
|
46
|
+
*/
|
|
47
|
+
const HOME_API_ACCESS_SCOPES = ["builder", "whoami"] as const;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Resolved shape of a `home.apiAccess()` grant. Keyless by design — there is
|
|
51
|
+
* no token here, only the socket to talk to. `socket` is the mount for the
|
|
52
|
+
* per-app proxy DIRECTORY (connect to `home-proxy.sock` inside it — a file
|
|
53
|
+
* bind-mount of a unix socket doesn't wire across containers on macOS Docker),
|
|
54
|
+
* fixed at `readOnly: true` because relaying a request needs no write access to
|
|
55
|
+
* the directory. This kind's `resolve` hook builds it from the app's per-app
|
|
56
|
+
* proxy dir (`/opt/realm/worker/home-proxy/<appId>`) at eval time.
|
|
57
|
+
*/
|
|
58
|
+
export interface HomeApiAccessValue {
|
|
59
|
+
readonly socket: WorkerMount;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Type-level placeholder: `apiAccess`'s resolver builds the real per-app value,
|
|
63
|
+
// and this only exists so `ValueOf` can read the shape off `toValue`. Empty
|
|
64
|
+
// hostPath stands in for "never resolved"; only the host path is per-app.
|
|
65
|
+
const HOME_API_PLACEHOLDER: HomeApiAccessValue = {
|
|
66
|
+
socket: { ...homeProxyMount(""), hostPath: "" as WorkerHostPath },
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Call your Home's control-plane API from this app, over the worker.
|
|
71
|
+
*
|
|
72
|
+
* The app container holds no uplink — only the Worker does — so it can't
|
|
73
|
+
* reach Home directly. `apiAccess` mounts a per-app worker socket dir
|
|
74
|
+
* (holding `home-proxy.sock`); the worker turns the request into one `apiAccess`
|
|
75
|
+
* call on its uplink, which Home dispatches to `/api-access/*`, and relays the
|
|
76
|
+
* response back.
|
|
77
|
+
*
|
|
78
|
+
* Keyless: the app holds no credential. Identity is the socket it arrived on
|
|
79
|
+
* (the worker asserts `X-Realm-App-Id`); authorization is the scopes you
|
|
80
|
+
* granted, enforced by Home. Resolves to `{ socket }` (the per-app socket
|
|
81
|
+
* DIRECTORY) — mount it as a volume and call `callHome`. The grant exempts the
|
|
82
|
+
* resolved dir from the absolute-mount gate, so a bare `apiAccess` is
|
|
83
|
+
* enough to wire it.
|
|
84
|
+
*
|
|
85
|
+
* Only a single app (`createApp`) may declare this. One app holding a Home
|
|
86
|
+
* control-plane socket on every box in the fleet is a much larger surface
|
|
87
|
+
* than one holding a single socket.
|
|
88
|
+
*
|
|
89
|
+
* @see https://yourrealm.eu/docs/realm-ts/home/api-access/
|
|
90
|
+
*/
|
|
91
|
+
export const apiAccess = homeable(
|
|
92
|
+
"home.apiAccess",
|
|
93
|
+
z.array(z.enum(HOME_API_ACCESS_SCOPES)).min(1),
|
|
94
|
+
{
|
|
95
|
+
// No elevated *use* to collect — mounting the socket falls out of the
|
|
96
|
+
// grant being in place; the resolved socket is exempted from the
|
|
97
|
+
// absolute-mount gate via `collectAllowed` in the Home eval graph.
|
|
98
|
+
iterateUses: () => [],
|
|
99
|
+
// Type-level only; every real value comes from `resolve`, since the
|
|
100
|
+
// socket is per-app and the grant carries only scopes.
|
|
101
|
+
toValue: (): HomeApiAccessValue => HOME_API_PLACEHOLDER,
|
|
102
|
+
// The value the app mounts is the per-app DIRECTORY; the wire carries the
|
|
103
|
+
// socket file inside it (the path the worker binds).
|
|
104
|
+
resolve: ({ ctx }): HomeApiAccessValue => ({ socket: homeProxyMount(ctx.appId) }),
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "Home API access",
|
|
108
|
+
phrase: "call the Home control-plane API",
|
|
109
|
+
helpText:
|
|
110
|
+
"This app can call your Home's control-plane API (over the worker) to use the capabilities you grant — e.g. pinning the images it builds. It holds no key; the worker proves which app it is.",
|
|
111
|
+
icon: "GearIcon",
|
|
112
|
+
danger: true,
|
|
113
|
+
// Single-only: a fleet-wide app holding a Home API socket on every
|
|
114
|
+
// box is a materially larger surface than one holding a single
|
|
115
|
+
// socket, and `builder` (the only scope with reach) is a singleton.
|
|
116
|
+
appKinds: "single",
|
|
117
|
+
},
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* What an ungranted (or not-yet-filled) `publicDomain` resolves to. Not an
|
|
122
|
+
* error state: it is what an operator who installed now and will add the
|
|
123
|
+
* domain later has, and it emits no public route.
|
|
124
|
+
*/
|
|
125
|
+
const NO_PUBLIC_DOMAIN: PublicDomainValue = { hosts: [], domainMode: "redirect" };
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Serve this app on a hostname the operator owns.
|
|
129
|
+
*
|
|
130
|
+
* Every routed service already gets an authenticated subdomain under the
|
|
131
|
+
* Realm domain, so "reachable from the internet" is not what this adds. What
|
|
132
|
+
* it adds is a name the operator brings: a real URL, an origin the app owns
|
|
133
|
+
* (its own cookies, OIDC issuer, CORS and absolute links), its own
|
|
134
|
+
* certificate, and no per-request hop through Home's gate.
|
|
135
|
+
*
|
|
136
|
+
* The author declares the leaf and wires it; the *operator* supplies the
|
|
137
|
+
* hostname on the install screen, the same split as `host.silo`. So there is
|
|
138
|
+
* no domain string anywhere in a realm.ts:
|
|
139
|
+
*
|
|
140
|
+
* ```ts
|
|
141
|
+
* domain: r.home
|
|
142
|
+
* .publicDomain()
|
|
143
|
+
* .reason("Serve your photos on your own domain")
|
|
144
|
+
* .optional(),
|
|
145
|
+
* // ...
|
|
146
|
+
* router: { containerPort: 2283, publicDomain: config.domain },
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* A custom domain is necessarily **ungated**: Home cannot run its login on a
|
|
150
|
+
* domain it does not own (the `.{baseDomain}` session cookie can't reach it),
|
|
151
|
+
* so the app owns its own auth here. The gated auto subdomain keeps working
|
|
152
|
+
* alongside it.
|
|
153
|
+
*
|
|
154
|
+
* **Declare it `.optional()`.** There is no required variant in v1, and a
|
|
155
|
+
* required one breaks in two directions: a parked template is a row nobody can
|
|
156
|
+
* open an install screen for, and so is a pinless `build:` app. Nothing is
|
|
157
|
+
* broken without a custom domain anyway - the gated auto subdomain always
|
|
158
|
+
* exists, and an ungranted leaf resolves to `undefined`, which emits no public
|
|
159
|
+
* route.
|
|
160
|
+
*
|
|
161
|
+
* A preview child never serves one. It inherits its template's grants
|
|
162
|
+
* verbatim, so Home clears the resolved value for any `role: preview` app -
|
|
163
|
+
* without that, every child of one template would claim the same host.
|
|
164
|
+
*
|
|
165
|
+
* Only a single app (`createApp`) may declare this. A hostname resolves to
|
|
166
|
+
* one box, so a grant spread across a fleet would claim a name every worker
|
|
167
|
+
* would then fight over.
|
|
168
|
+
*
|
|
169
|
+
* @see https://yourrealm.eu/docs/realm-ts/home/public-domain/
|
|
170
|
+
*/
|
|
171
|
+
export const publicDomain = homeable(
|
|
172
|
+
"home.publicDomain",
|
|
173
|
+
// Empty author data. `z.literal(true)` rather than `z.void()` leaves the
|
|
174
|
+
// slot for `publicDomain({ wildcard: true })` without changing any call
|
|
175
|
+
// site: the author declares cardinality, the operator only ever chooses
|
|
176
|
+
// which domain.
|
|
177
|
+
z.literal(true).default(true),
|
|
178
|
+
{
|
|
179
|
+
// Unlike the rest of `home.*` this kind has a real per-service use: the
|
|
180
|
+
// hosts a router actually serves on. `checkAppGrants` matches them against
|
|
181
|
+
// the granted set, so a packed bundle can't hand the VM a router carrying
|
|
182
|
+
// a host the operator never approved. Routers with no hosts emit nothing —
|
|
183
|
+
// there is no elevated thing being done.
|
|
184
|
+
iterateUses: function* (svc) {
|
|
185
|
+
const value = svc.router?.publicDomain;
|
|
186
|
+
if (value && value.hosts.length > 0) yield value;
|
|
187
|
+
},
|
|
188
|
+
// The grant holds the whole answer (the operator's hosts + their redirect
|
|
189
|
+
// choice), so there is no `resolve` hook — branding is all that separates
|
|
190
|
+
// stored data from the resolved value.
|
|
191
|
+
//
|
|
192
|
+
// Total on purpose: the speculative-eval paths build grants straight off
|
|
193
|
+
// the descriptors with an empty `grantValues` map, and this kind has no
|
|
194
|
+
// `perm.data` to fall back to, so throwing on `undefined` would drop the
|
|
195
|
+
// image cards off the install screen of every app that declares it.
|
|
196
|
+
toValue: (data: PublicDomainGrantData | undefined): PublicDomainValue =>
|
|
197
|
+
data == null
|
|
198
|
+
? NO_PUBLIC_DOMAIN
|
|
199
|
+
: { hosts: data.hosts as PublicDomain[], domainMode: data.domainMode },
|
|
200
|
+
// Descriptor data and grant data diverge, the `host.silo` shape: the
|
|
201
|
+
// author declares nothing but intent, the operator supplies the hosts.
|
|
202
|
+
// The default is what an enabled-but-untouched toggle stores, and it is
|
|
203
|
+
// the "no route" value rather than an error, because adding the domain
|
|
204
|
+
// later is a normal install-then-configure flow.
|
|
205
|
+
grantSchema: publicDomainValueSchema.default({ hosts: [], domainMode: "redirect" }),
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
name: "Public domain",
|
|
209
|
+
phrase: "serve this app on a domain you own",
|
|
210
|
+
helpText:
|
|
211
|
+
"This app is served on a hostname you supply, outside your Realm domain and without Home's login in front of it. Anyone who can reach the name reaches the app, so only grant it to an app whose own authentication you trust.",
|
|
212
|
+
icon: "GlobeIcon",
|
|
213
|
+
// Single-only: a hostname points at one box. Fanning the same name
|
|
214
|
+
// across every worker would have them all claim it.
|
|
215
|
+
appKinds: "single",
|
|
216
|
+
},
|
|
217
|
+
);
|