openship 0.6.5 → 0.6.7
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/bare-7QD623QV.js +29 -0
- package/dist/chunk-2ANV5ZQ5.js +88 -0
- package/dist/{chunk-LEYSL46B.js → chunk-2VSW6Q6C.js} +3911 -898
- package/dist/{chunk-5OUWIPOB.js → chunk-5T4UVOM3.js} +16 -86
- package/dist/{chunk-EZPPTWJQ.js → chunk-BLEXTYRK.js} +1 -1
- package/dist/{chunk-3ZAGC5NT.js → chunk-CIJV43LH.js} +83 -33
- package/dist/{chunk-7S4USQYF.js → chunk-DDFUESPJ.js} +67 -124
- package/dist/{chunk-6FH4AXVY.js → chunk-E2X26PXR.js} +1 -1
- package/dist/{chunk-XVOBL7BC.js → chunk-FYPFEDPZ.js} +1 -1
- package/dist/{chunk-WFRXYWK2.js → chunk-FZ6QCF6B.js} +8 -6
- package/dist/{chunk-VHMOQL5Y.js → chunk-GGIAIGUL.js} +125 -80
- package/dist/{chunk-WE7BXW6L.js → chunk-GIPJNNI5.js} +38 -44
- package/dist/{chunk-ZFJXPCQP.js → chunk-H3WT3A6R.js} +4 -3
- package/dist/chunk-H4FS5BED.js +936 -0
- package/dist/{chunk-HPXP6LXZ.js → chunk-J2XM3QSP.js} +8 -5
- package/dist/{chunk-6JELW75A.js → chunk-J3K6XABC.js} +5 -5
- package/dist/{chunk-VDESJSG6.js → chunk-LHFXSC36.js} +558 -109
- package/dist/{chunk-MSZUCNPV.js → chunk-MEE6OZFP.js} +3 -3
- package/dist/chunk-N5YZMO33.js +111 -0
- package/dist/{chunk-VLQ3UIVO.js → chunk-NRTJRNAE.js} +105 -37
- package/dist/chunk-PPEBIY5F.js +2331 -0
- package/dist/{chunk-RFWJE7ZN.js → chunk-PVP4RGWT.js} +3 -3
- package/dist/{chunk-PZRRL5PC.js → chunk-QHMDCYZ3.js} +15 -4
- package/dist/chunk-R4VDPFLS.js +106 -0
- package/dist/chunk-RDXT4BQB.js +310 -0
- package/dist/{chunk-GRTXMUHA.js → chunk-S6B2Z3OO.js} +145 -60
- package/dist/chunk-UWEV6XTS.js +249 -0
- package/dist/{chunk-QLX7NBEA.js → chunk-VQM6JHJB.js} +1004 -2046
- package/dist/{chunk-A7EWM2KA.js → chunk-VSTFHUCV.js} +44 -50
- package/dist/chunk-WU54BXFE.js +70 -0
- package/dist/{chunk-LFCSC4IU.js → chunk-XWHWTHEL.js} +313 -469
- package/dist/{chunk-7334NSJL.js → chunk-ZPJ74LXE.js} +76 -38
- package/dist/cloud-KNNABE3O.js +40 -0
- package/dist/{detect-P4CIQBRH.js → detect-G4DR3U2N.js} +9 -6
- package/dist/{docker-3K2NEBD6.js → docker-YOVPCIB4.js} +11 -7
- package/dist/{docker-edge-executor-YZZ6P7IC.js → docker-edge-executor-QFXD3337.js} +8 -6
- package/dist/edge-import-CRFVSR6P.js +56 -0
- package/dist/{edge-preflight-ES6FH4JK.js → edge-preflight-MXERVAMG.js} +15 -12
- package/dist/{ensure-container-edge-YPITNH45.js → ensure-container-edge-F4JUNQIK.js} +13 -10
- package/dist/{executor-DZGX55K2.js → executor-CVPAYYHR.js} +10 -5
- package/dist/host-channel-preflight-QTDNGLCK.js +54 -0
- package/dist/index.js +139 -92
- package/dist/{local-executor-WOFZD72X.js → local-executor-ODC6RANU.js} +3 -2
- package/dist/{nginx-NSAHWGJV.js → nginx-KLFF43TC.js} +13 -8
- package/dist/{openresty-lua-DR4D3EZ6.js → openresty-lua-VKWUV4GB.js} +8 -5
- package/dist/{privilege-YTVI4SKF.js → privilege-7D3SSOL3.js} +6 -5
- package/dist/server/engine/samples/amavisd/amavisd.conf +25 -0
- package/dist/server/engine/samples/postfix/master.cf +14 -0
- package/dist/server/index.js +44526 -33476
- package/dist/server/migrations/0105_mail_inbound_rules.sql +80 -0
- package/dist/server/migrations/0106_mcp_call_tracking.sql +23 -0
- package/dist/server/migrations/0107_build_minute_metering_indexes.sql +20 -0
- package/dist/server/migrations/0108_credential.sql +68 -0
- package/dist/server/migrations/meta/_journal.json +28 -0
- package/dist/setup-I5AJC6NJ.js +25 -0
- package/dist/ssh-client-625VWGKP.js +29 -0
- package/dist/up-QXTOOVXC.js +61 -0
- package/package.json +1 -1
- package/dist/bare-XQIPDO4R.js +0 -24
- package/dist/chunk-6HOA5JT7.js +0 -124
- package/dist/chunk-TM2IQPYU.js +0 -434
- package/dist/chunk-XRNRT37W.js +0 -316
- package/dist/cloud-3DODOWTR.js +0 -36
- package/dist/edge-import-MCJNVTZ2.js +0 -51
- package/dist/host-channel-preflight-MUXE3KZU.js +0 -49
- package/dist/setup-WUUZURHS.js +0 -22
- package/dist/up-XEO3SR6Z.js +0 -58
- /package/dist/{dist-es-ZP5QDSJ3.js → dist-es-AXFRS7PS.js} +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
-- Inbound-mail notification rules — "mail arrives at a watched address, tell me in a channel".
|
|
2
|
+
--
|
|
3
|
+
-- Capture is Postfix's own `recipient_bcc_maps`, which the shipped main.cf already points
|
|
4
|
+
-- at two SQL tables in the engine's `vmail` DB (main.cf.pgsql:36-38). Arming a rule is
|
|
5
|
+
-- therefore ONE row in `vmail.recipient_bcc_domain` — no postmap, no reload, no container
|
|
6
|
+
-- recreate, and identical on the container and legacy host flavors, so it reaches every
|
|
7
|
+
-- mail box already provisioned.
|
|
8
|
+
--
|
|
9
|
+
-- ONE TABLE, ON PURPOSE. The obvious second table — a record of each armed collector —
|
|
10
|
+
-- would only cache state the mail engine already holds authoritatively: the token is
|
|
11
|
+
-- literally inside `recipient_bcc_domain.bcc_address`
|
|
12
|
+
-- (`openship-hook+<token>@<domain>`), the maildir is in `vmail.mailbox`, and "a foreign
|
|
13
|
+
-- BCC took the slot" is derivable by comparing that address against our own prefix. A
|
|
14
|
+
-- cache of the engine's own state is a thing that goes stale; the collector is READ from
|
|
15
|
+
-- vmail instead.
|
|
16
|
+
--
|
|
17
|
+
-- What genuinely has to persist here is the RULES: they reference
|
|
18
|
+
-- `notification_channel` ids, which exist only in this database, and they are created and
|
|
19
|
+
-- edited from a dashboard tab. Keeping them on the mail box would make every list and
|
|
20
|
+
-- toggle an SSH round-trip, and would make the rules unreadable exactly when the mail box
|
|
21
|
+
-- is unreachable.
|
|
22
|
+
--
|
|
23
|
+
-- No cursor table either. The BCC copy is a full message in the collector's maildir, so
|
|
24
|
+
-- the read job dispatches and then DELETES the file: deletion is the cursor, and it
|
|
25
|
+
-- doubles as the prune that keeps a second full copy of every watched message from
|
|
26
|
+
-- growing forever on a bind mount with no quota of its own.
|
|
27
|
+
CREATE TABLE IF NOT EXISTS "mail_inbound_rule" (
|
|
28
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
29
|
+
"server_id" text NOT NULL REFERENCES "mail_servers"("server_id") ON DELETE CASCADE,
|
|
30
|
+
-- Carried so dispatch can fan out to the right org's channels without joining back
|
|
31
|
+
-- through `servers`. This does NOT make the table organization-scope for dump purposes
|
|
32
|
+
-- (see dump.ts): its FK targets are instance-scope.
|
|
33
|
+
"organization_id" text NOT NULL REFERENCES "organization"("id") ON DELETE CASCADE,
|
|
34
|
+
-- Operator-facing label, e.g. "Support inbox → #support".
|
|
35
|
+
"name" text NOT NULL,
|
|
36
|
+
-- mailbox | domain | all. Text, not an enum: a new scope should be a registry entry and
|
|
37
|
+
-- a UI option, not a migration.
|
|
38
|
+
"scope" text NOT NULL,
|
|
39
|
+
-- Full address for `mailbox`, the domain for `domain`, NULL for `all`.
|
|
40
|
+
--
|
|
41
|
+
-- `all` is a genuine fan-out: there is no global `always_bcc` anywhere in the shipped
|
|
42
|
+
-- Postfix config, and the domain lookup keys on exact equality with no wildcard
|
|
43
|
+
-- convention — so it arms one row per domain and needs a reconcile when a domain is
|
|
44
|
+
-- added. There is deliberately no CHECK tying scope to target: this schema has no CHECK
|
|
45
|
+
-- constraints anywhere, and the SQL and the drizzle schema are hand-maintained in
|
|
46
|
+
-- parallel. The invariant is enforced fail-closed at the write boundary and in the
|
|
47
|
+
-- filter, where a mailbox rule with no target matches NOTHING rather than everything.
|
|
48
|
+
"target" text,
|
|
49
|
+
-- Optional extra matching, applied in the control plane at filter time so editing one
|
|
50
|
+
-- never touches the mail box. NULL = match everything.
|
|
51
|
+
"from_pattern" text,
|
|
52
|
+
"subject_pattern" text,
|
|
53
|
+
-- Spam gate, and not optional in practice. The shipped amavis policy sets
|
|
54
|
+
-- spam_lover='Y' AND bad_header_lover='Y' on the catch-all '@.' policy with empty
|
|
55
|
+
-- quarantine targets, so the global $final_spam_destiny = D_DISCARD is dead for every
|
|
56
|
+
-- recipient: spam and bad-header mail ARE delivered and therefore ARE captured.
|
|
57
|
+
-- Nothing upstream filters on our behalf.
|
|
58
|
+
"max_spam_score" real,
|
|
59
|
+
-- Channel ids as a jsonb array, deliberately NOT a join table with an FK to
|
|
60
|
+
-- notification_channel: the dump's FK_PARENT maps a bare `channelId` column to that
|
|
61
|
+
-- table unconditionally for ANY table, which would make assertDumpSelfContained reject
|
|
62
|
+
-- any dump carrying a real join row on a remap path.
|
|
63
|
+
"channel_ids" jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
64
|
+
"enabled" boolean NOT NULL DEFAULT true,
|
|
65
|
+
-- Burst control state. The notification subsystem has no rate limiting or windowed
|
|
66
|
+
-- dedup of its own — that is explicitly the producer's job — so a mailing list hitting
|
|
67
|
+
-- a watched address must not become one alert per message.
|
|
68
|
+
"paused_reason" text,
|
|
69
|
+
"last_matched_at" timestamp,
|
|
70
|
+
"created_at" timestamp NOT NULL DEFAULT now(),
|
|
71
|
+
"updated_at" timestamp NOT NULL DEFAULT now()
|
|
72
|
+
);
|
|
73
|
+
--> statement-breakpoint
|
|
74
|
+
-- The dispatch path's read on every tick: "enabled rules for this server".
|
|
75
|
+
CREATE INDEX IF NOT EXISTS "idx_mail_inbound_rule_server_enabled"
|
|
76
|
+
ON "mail_inbound_rule" ("server_id", "enabled");
|
|
77
|
+
--> statement-breakpoint
|
|
78
|
+
-- The rules tab lists per org.
|
|
79
|
+
CREATE INDEX IF NOT EXISTS "idx_mail_inbound_rule_org"
|
|
80
|
+
ON "mail_inbound_rule" ("organization_id");
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
-- MCP observability: attribute an audit row to the CLIENT that made it, and
|
|
2
|
+
-- count how much a credential is used.
|
|
3
|
+
--
|
|
4
|
+
-- `source` already said "an AI assistant did this" (0088), unforgeably — but not
|
|
5
|
+
-- WHICH assistant. With two clients connected under one user (Claude Desktop and
|
|
6
|
+
-- Cursor, say) every row read the same, so "what did this agent do" could not be
|
|
7
|
+
-- answered and disconnecting the wrong one was a coin flip. The column holds the
|
|
8
|
+
-- canonical principal id the auth layer already mints (`oauth:<clientId>` /
|
|
9
|
+
-- `pat:<tokenId>`), so it resolves to a name through existing tables.
|
|
10
|
+
--
|
|
11
|
+
-- The index is PARTIAL: only MCP rows ever carry a client id, and mcp.tool_called
|
|
12
|
+
-- makes audit_event's highest-volume writer, so indexing the NULLs would be paid
|
|
13
|
+
-- for on every insert in the table for no read.
|
|
14
|
+
ALTER TABLE "audit_event" ADD COLUMN IF NOT EXISTS "source_client_id" text;--> statement-breakpoint
|
|
15
|
+
CREATE INDEX IF NOT EXISTS "audit_event_org_client_idx"
|
|
16
|
+
ON "audit_event" ("organization_id", "source_client_id", "created_at" DESC)
|
|
17
|
+
WHERE "source_client_id" IS NOT NULL;--> statement-breakpoint
|
|
18
|
+
|
|
19
|
+
-- Call counter for every bearer credential (manual PATs and the OAuth-binding
|
|
20
|
+
-- rows behind MCP connections alike). NOT NULL DEFAULT 0 is safe here: existing
|
|
21
|
+
-- rows genuinely have no counted history, and 0 alongside a non-null
|
|
22
|
+
-- `last_used_at` reads correctly as "used before counting existed".
|
|
23
|
+
ALTER TABLE "personal_access_token" ADD COLUMN IF NOT EXISTS "use_count" integer DEFAULT 0 NOT NULL;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- Indexes for the build-minute allowance query.
|
|
2
|
+
--
|
|
3
|
+
-- `sumBuildMillisForOrg` joins build_session → deployment, filters on
|
|
4
|
+
-- deployment.organization_id and windows on build_session.started_at. It used to
|
|
5
|
+
-- run only on the billing page (once, on demand); it now runs on the plan gate in
|
|
6
|
+
-- `createQueuedDeployment`, i.e. on every deploy. Neither side of that join had a
|
|
7
|
+
-- supporting index — build_session carried only its primary key and
|
|
8
|
+
-- deployment.organization_id had none — so the query was a double sequential scan
|
|
9
|
+
-- whose cost grows with TOTAL deployment history across all orgs, not with the
|
|
10
|
+
-- org being checked.
|
|
11
|
+
--
|
|
12
|
+
-- (domain.project_id, which the free-subdomain count joins on, is already covered
|
|
13
|
+
-- by idx_domain_project.)
|
|
14
|
+
CREATE INDEX IF NOT EXISTS "idx_build_session_started_at"
|
|
15
|
+
ON "build_session" ("started_at");--> statement-breakpoint
|
|
16
|
+
|
|
17
|
+
-- Org scoping for the same join. Also serves the org-wide deployment listings,
|
|
18
|
+
-- which had been scanning for the same reason.
|
|
19
|
+
CREATE INDEX IF NOT EXISTS "idx_deployment_org"
|
|
20
|
+
ON "deployment" ("organization_id");
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
-- Third-party credentials, in one place.
|
|
2
|
+
--
|
|
3
|
+
-- Openship needs other people's secrets for unrelated jobs — write a DNS record, pull a
|
|
4
|
+
-- private image, later push a backup — and each job grew its own storage: a single token
|
|
5
|
+
-- column on `dns_credential`, FIVE encrypted columns inlined on a backup destination, a
|
|
6
|
+
-- channel's own on notifications. Same `enc1:` envelope in each, three shapes, three
|
|
7
|
+
-- forms in the UI, and no way to reuse one credential for two features.
|
|
8
|
+
--
|
|
9
|
+
-- The unit here is the CREDENTIAL, deliberately not the thing that uses it. A backup
|
|
10
|
+
-- destination is a place, a DNS zone is a zone, a notification channel is a route; each
|
|
11
|
+
-- keeps its own row and points at a credential. That is what makes "one Cloudflare token
|
|
12
|
+
-- for every zone" and "one ghcr.io login for every project" possible — the reuse is the
|
|
13
|
+
-- point, fewer screens is the side effect.
|
|
14
|
+
--
|
|
15
|
+
-- Shape notes:
|
|
16
|
+
-- • `provider` is TEXT, matching dns_credential's reasoning: adding a provider should
|
|
17
|
+
-- be a registry entry in @repo/core, not a migration.
|
|
18
|
+
-- • `selector` is what the credential APPLIES TO when one per provider is not enough —
|
|
19
|
+
-- a registry host for `docker-registry`, NULL for an org-wide `cloudflare` token. It
|
|
20
|
+
-- is stored normalized (see normalizeCredentialSelector) so the value a pull derives
|
|
21
|
+
-- from an image reference matches the value the operator typed.
|
|
22
|
+
-- • `secrets_enc` is ONE `enc1:` AES-256-GCM envelope over a JSON object, so a provider
|
|
23
|
+
-- with several secret fields (an S3 key pair, an SFTP key + passphrase) needs no new
|
|
24
|
+
-- columns. The readable half lives in `public_fields`, which is what the API can
|
|
25
|
+
-- return without decrypting anything.
|
|
26
|
+
-- • `status` + `last_error` exist so a credential that was revoked upstream becomes
|
|
27
|
+
-- VISIBLE instead of silently failing every deploy or backup forever. `last_error` is
|
|
28
|
+
-- the provider's redacted reason, never its response body.
|
|
29
|
+
CREATE TABLE IF NOT EXISTS "credential" (
|
|
30
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
31
|
+
"organization_id" text NOT NULL REFERENCES "organization"("id") ON DELETE CASCADE,
|
|
32
|
+
-- Provider id from CREDENTIAL_PROVIDERS ("docker-registry", "cloudflare").
|
|
33
|
+
"provider" text NOT NULL,
|
|
34
|
+
-- Operator-facing label, e.g. "GHCR read-only".
|
|
35
|
+
"name" text NOT NULL,
|
|
36
|
+
-- The resource this credential is for, normalized; NULL when the provider is org-wide.
|
|
37
|
+
"selector" text,
|
|
38
|
+
-- Non-secret fields (username, region, endpoint) — returned by the API as-is.
|
|
39
|
+
"public_fields" jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
40
|
+
-- Every secret field for this provider, as one enc1: envelope over a JSON object.
|
|
41
|
+
"secrets_enc" text NOT NULL,
|
|
42
|
+
-- active | invalid. Flipped to 'invalid' the moment a provider answers 401/403, which
|
|
43
|
+
-- is the only time we learn a stored credential stopped working.
|
|
44
|
+
"status" text NOT NULL DEFAULT 'active',
|
|
45
|
+
"last_verified_at" timestamp,
|
|
46
|
+
-- Redacted reason the last verify or use failed. Never provider response bodies.
|
|
47
|
+
"last_error" text,
|
|
48
|
+
"created_at" timestamp NOT NULL DEFAULT now(),
|
|
49
|
+
"updated_at" timestamp NOT NULL DEFAULT now()
|
|
50
|
+
);
|
|
51
|
+
--> statement-breakpoint
|
|
52
|
+
-- The resolve path asks exactly one question — "this org's credential for this provider
|
|
53
|
+
-- and this resource" — on every deploy that pulls and every domain that provisions.
|
|
54
|
+
-- Leading org column means the plain org-wide listing and the per-provider listing both
|
|
55
|
+
-- ride this index as prefixes, so it is the only lookup index the table needs. `status`
|
|
56
|
+
-- is filtered in code: a handful of rows per org makes an extra column here dead weight.
|
|
57
|
+
CREATE INDEX IF NOT EXISTS "idx_credential_org_provider_selector"
|
|
58
|
+
ON "credential" ("organization_id", "provider", "selector");
|
|
59
|
+
--> statement-breakpoint
|
|
60
|
+
-- One label per provider per resource per org. A second "GHCR read-only" for the same
|
|
61
|
+
-- host is a double-submit, and two credentials matching one registry makes "which one
|
|
62
|
+
-- authenticated this pull" unanswerable when one of them starts failing.
|
|
63
|
+
--
|
|
64
|
+
-- COALESCE, not a bare column: Postgres treats NULLs as DISTINCT in a unique index, so
|
|
65
|
+
-- an org-wide provider (selector IS NULL — every Cloudflare token) would accept
|
|
66
|
+
-- unlimited duplicates of the same name and this constraint would quietly do nothing.
|
|
67
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "uq_credential_org_provider_selector_name"
|
|
68
|
+
ON "credential" ("organization_id", "provider", COALESCE("selector", ''), "name");
|
|
@@ -736,6 +736,34 @@
|
|
|
736
736
|
"when": 1787955707325,
|
|
737
737
|
"tag": "0104_instance_host_control",
|
|
738
738
|
"breakpoints": true
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
"idx": 105,
|
|
742
|
+
"version": "7",
|
|
743
|
+
"when": 1788042107325,
|
|
744
|
+
"tag": "0105_mail_inbound_rules",
|
|
745
|
+
"breakpoints": true
|
|
746
|
+
},
|
|
747
|
+
{
|
|
748
|
+
"idx": 106,
|
|
749
|
+
"version": "7",
|
|
750
|
+
"when": 1788128507325,
|
|
751
|
+
"tag": "0106_mcp_call_tracking",
|
|
752
|
+
"breakpoints": true
|
|
753
|
+
},
|
|
754
|
+
{
|
|
755
|
+
"idx": 107,
|
|
756
|
+
"version": "7",
|
|
757
|
+
"when": 1788214907325,
|
|
758
|
+
"tag": "0107_build_minute_metering_indexes",
|
|
759
|
+
"breakpoints": true
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
"idx": 108,
|
|
763
|
+
"version": "7",
|
|
764
|
+
"when": 1788301307325,
|
|
765
|
+
"tag": "0108_credential",
|
|
766
|
+
"breakpoints": true
|
|
739
767
|
}
|
|
740
768
|
]
|
|
741
769
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
|
+
import { createRequire as __ospCreateRequire } from "node:module";
|
|
4
|
+
const require = __ospCreateRequire(import.meta.url);
|
|
5
|
+
import {
|
|
6
|
+
SystemManager
|
|
7
|
+
} from "./chunk-FYPFEDPZ.js";
|
|
8
|
+
import "./chunk-ZPJ74LXE.js";
|
|
9
|
+
import "./chunk-NRTJRNAE.js";
|
|
10
|
+
import "./chunk-QHMDCYZ3.js";
|
|
11
|
+
import "./chunk-I3DPMTSF.js";
|
|
12
|
+
import "./chunk-R4VDPFLS.js";
|
|
13
|
+
import "./chunk-PVP4RGWT.js";
|
|
14
|
+
import "./chunk-BLEXTYRK.js";
|
|
15
|
+
import "./chunk-FZ6QCF6B.js";
|
|
16
|
+
import "./chunk-H3WT3A6R.js";
|
|
17
|
+
import "./chunk-GIPJNNI5.js";
|
|
18
|
+
import "./chunk-VSTFHUCV.js";
|
|
19
|
+
import "./chunk-UWEV6XTS.js";
|
|
20
|
+
import "./chunk-N5YZMO33.js";
|
|
21
|
+
import "./chunk-2VSW6Q6C.js";
|
|
22
|
+
import "./chunk-PXKCZB2I.js";
|
|
23
|
+
export {
|
|
24
|
+
SystemManager
|
|
25
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
|
+
import { createRequire as __ospCreateRequire } from "node:module";
|
|
4
|
+
const require = __ospCreateRequire(import.meta.url);
|
|
5
|
+
import {
|
|
6
|
+
DOCKER_DIAL_STDIO_COMMAND,
|
|
7
|
+
attachDialStdioDiagnostics,
|
|
8
|
+
connectSshClient,
|
|
9
|
+
dialStdioDiagnostics,
|
|
10
|
+
execSshCommand,
|
|
11
|
+
openDockerDialStdioChannel,
|
|
12
|
+
openSftp,
|
|
13
|
+
openSshExecChannel,
|
|
14
|
+
openSshUnixSocket
|
|
15
|
+
} from "./chunk-5T4UVOM3.js";
|
|
16
|
+
import "./chunk-N5YZMO33.js";
|
|
17
|
+
import "./chunk-2VSW6Q6C.js";
|
|
18
|
+
import "./chunk-PXKCZB2I.js";
|
|
19
|
+
export {
|
|
20
|
+
DOCKER_DIAL_STDIO_COMMAND,
|
|
21
|
+
attachDialStdioDiagnostics,
|
|
22
|
+
connectSshClient,
|
|
23
|
+
dialStdioDiagnostics,
|
|
24
|
+
execSshCommand,
|
|
25
|
+
openDockerDialStdioChannel,
|
|
26
|
+
openSftp,
|
|
27
|
+
openSshExecChannel,
|
|
28
|
+
openSshUnixSocket
|
|
29
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
|
+
import { createRequire as __ospCreateRequire } from "node:module";
|
|
4
|
+
const require = __ospCreateRequire(import.meta.url);
|
|
5
|
+
import {
|
|
6
|
+
normalizeUrl,
|
|
7
|
+
runHeadlessProvision,
|
|
8
|
+
startService,
|
|
9
|
+
upCommand
|
|
10
|
+
} from "./chunk-DDFUESPJ.js";
|
|
11
|
+
import "./chunk-PPEBIY5F.js";
|
|
12
|
+
import "./chunk-RDXT4BQB.js";
|
|
13
|
+
import "./chunk-VQM6JHJB.js";
|
|
14
|
+
import "./chunk-QWHBRY2K.js";
|
|
15
|
+
import "./chunk-J2XM3QSP.js";
|
|
16
|
+
import "./chunk-ELGRMZOW.js";
|
|
17
|
+
import "./chunk-FYPFEDPZ.js";
|
|
18
|
+
import "./chunk-ONKEYSMY.js";
|
|
19
|
+
import "./chunk-XZYFZ6A5.js";
|
|
20
|
+
import "./chunk-PDW4L3NV.js";
|
|
21
|
+
import "./chunk-DOD2BXHQ.js";
|
|
22
|
+
import "./chunk-42WQABXM.js";
|
|
23
|
+
import "./chunk-DRK3MEDS.js";
|
|
24
|
+
import "./chunk-3NQQXMDR.js";
|
|
25
|
+
import "./chunk-ZWLDLTJP.js";
|
|
26
|
+
import "./chunk-J3K6XABC.js";
|
|
27
|
+
import "./chunk-CIJV43LH.js";
|
|
28
|
+
import "./chunk-ZPJ74LXE.js";
|
|
29
|
+
import "./chunk-NRTJRNAE.js";
|
|
30
|
+
import "./chunk-QHMDCYZ3.js";
|
|
31
|
+
import "./chunk-I3DPMTSF.js";
|
|
32
|
+
import "./chunk-WNWQBB7F.js";
|
|
33
|
+
import "./chunk-2GWYYHOR.js";
|
|
34
|
+
import "./chunk-RXQBD4ZY.js";
|
|
35
|
+
import "./chunk-LHFXSC36.js";
|
|
36
|
+
import "./chunk-XWHWTHEL.js";
|
|
37
|
+
import "./chunk-S6B2Z3OO.js";
|
|
38
|
+
import "./chunk-MEE6OZFP.js";
|
|
39
|
+
import "./chunk-WU54BXFE.js";
|
|
40
|
+
import "./chunk-H4FS5BED.js";
|
|
41
|
+
import "./chunk-GGIAIGUL.js";
|
|
42
|
+
import "./chunk-R4VDPFLS.js";
|
|
43
|
+
import "./chunk-2ANV5ZQ5.js";
|
|
44
|
+
import "./chunk-5T4UVOM3.js";
|
|
45
|
+
import "./chunk-E2X26PXR.js";
|
|
46
|
+
import "./chunk-PVP4RGWT.js";
|
|
47
|
+
import "./chunk-BLEXTYRK.js";
|
|
48
|
+
import "./chunk-FZ6QCF6B.js";
|
|
49
|
+
import "./chunk-H3WT3A6R.js";
|
|
50
|
+
import "./chunk-GIPJNNI5.js";
|
|
51
|
+
import "./chunk-VSTFHUCV.js";
|
|
52
|
+
import "./chunk-UWEV6XTS.js";
|
|
53
|
+
import "./chunk-N5YZMO33.js";
|
|
54
|
+
import "./chunk-2VSW6Q6C.js";
|
|
55
|
+
import "./chunk-PXKCZB2I.js";
|
|
56
|
+
export {
|
|
57
|
+
normalizeUrl,
|
|
58
|
+
runHeadlessProvision,
|
|
59
|
+
startService,
|
|
60
|
+
upCommand
|
|
61
|
+
};
|
package/package.json
CHANGED
package/dist/bare-XQIPDO4R.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env sh
|
|
2
|
-
":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
|
-
import { createRequire as __ospCreateRequire } from "node:module";
|
|
4
|
-
const require = __ospCreateRequire(import.meta.url);
|
|
5
|
-
import {
|
|
6
|
-
BareRuntime,
|
|
7
|
-
STATIC_RELEASE_BASE
|
|
8
|
-
} from "./chunk-GRTXMUHA.js";
|
|
9
|
-
import "./chunk-MSZUCNPV.js";
|
|
10
|
-
import "./chunk-TM2IQPYU.js";
|
|
11
|
-
import "./chunk-VHMOQL5Y.js";
|
|
12
|
-
import "./chunk-5OUWIPOB.js";
|
|
13
|
-
import "./chunk-6FH4AXVY.js";
|
|
14
|
-
import "./chunk-RFWJE7ZN.js";
|
|
15
|
-
import "./chunk-A7EWM2KA.js";
|
|
16
|
-
import "./chunk-EZPPTWJQ.js";
|
|
17
|
-
import "./chunk-WFRXYWK2.js";
|
|
18
|
-
import "./chunk-ZFJXPCQP.js";
|
|
19
|
-
import "./chunk-LEYSL46B.js";
|
|
20
|
-
import "./chunk-PXKCZB2I.js";
|
|
21
|
-
export {
|
|
22
|
-
BareRuntime,
|
|
23
|
-
STATIC_RELEASE_BASE
|
|
24
|
-
};
|
package/dist/chunk-6HOA5JT7.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env sh
|
|
2
|
-
":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
|
-
import { createRequire as __ospCreateRequire } from "node:module";
|
|
4
|
-
const require = __ospCreateRequire(import.meta.url);
|
|
5
|
-
import {
|
|
6
|
-
composeInternalToken,
|
|
7
|
-
startUnitHint
|
|
8
|
-
} from "./chunk-QLX7NBEA.js";
|
|
9
|
-
import {
|
|
10
|
-
LocalExecutor
|
|
11
|
-
} from "./chunk-6FH4AXVY.js";
|
|
12
|
-
import {
|
|
13
|
-
EDGE_CONTAINER_NAME,
|
|
14
|
-
edgeCrashReason
|
|
15
|
-
} from "./chunk-WE7BXW6L.js";
|
|
16
|
-
|
|
17
|
-
// src/lib/edge-import.ts
|
|
18
|
-
import chalk from "chalk";
|
|
19
|
-
import ora from "ora";
|
|
20
|
-
async function waitForApiHealth(port, tries) {
|
|
21
|
-
for (let i = 0; i < tries; i++) {
|
|
22
|
-
try {
|
|
23
|
-
const r = await fetch(`http://127.0.0.1:${port}/api/health`, { signal: AbortSignal.timeout(2e3) });
|
|
24
|
-
if (r.ok) return true;
|
|
25
|
-
} catch {
|
|
26
|
-
}
|
|
27
|
-
await new Promise((r) => setTimeout(r, 1e3));
|
|
28
|
-
}
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
async function waitForEdgeRunning(tries) {
|
|
32
|
-
const exec = new LocalExecutor();
|
|
33
|
-
for (let i = 0; i < tries; i++) {
|
|
34
|
-
const out = await exec.exec(`docker inspect -f '{{.State.Running}}' ${EDGE_CONTAINER_NAME}`).catch(() => "");
|
|
35
|
-
if (out.trim() === "true") return true;
|
|
36
|
-
await new Promise((r) => setTimeout(r, 1e3));
|
|
37
|
-
}
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
async function importMigratedSites(apiPort, sites, certPems, staticRootOverrides) {
|
|
41
|
-
const token = composeInternalToken();
|
|
42
|
-
if (!token) {
|
|
43
|
-
const error = "couldn't read the stack's internal token";
|
|
44
|
-
console.log(chalk.yellow(` Skipping site import \u2014 ${error}. Re-run to retry.
|
|
45
|
-
`));
|
|
46
|
-
return { ok: false, registered: [], error };
|
|
47
|
-
}
|
|
48
|
-
const spinner = ora(
|
|
49
|
-
`Importing ${sites.length} migrated site${sites.length === 1 ? "" : "s"} into the edge\u2026`
|
|
50
|
-
).start();
|
|
51
|
-
if (!await waitForApiHealth(apiPort, 60)) {
|
|
52
|
-
const error = "API didn't become healthy in time";
|
|
53
|
-
spinner.warn(`${error} \u2014 migrated sites not imported. Re-run \`openship up\` to retry.`);
|
|
54
|
-
return { ok: false, registered: [], error };
|
|
55
|
-
}
|
|
56
|
-
if (!await waitForEdgeRunning(60)) {
|
|
57
|
-
const error = `the ${EDGE_CONTAINER_NAME} container isn't running yet`;
|
|
58
|
-
spinner.warn(`${error} \u2014 migrated sites not imported. Re-run \`openship up\` to retry.`);
|
|
59
|
-
return { ok: false, registered: [], error };
|
|
60
|
-
}
|
|
61
|
-
try {
|
|
62
|
-
const r = await fetch(`http://127.0.0.1:${apiPort}/api/system/edge/import-sites`, {
|
|
63
|
-
method: "POST",
|
|
64
|
-
headers: { "Content-Type": "application/json", "X-Internal-Token": token },
|
|
65
|
-
body: JSON.stringify({ sites, certPems, staticRootOverrides }),
|
|
66
|
-
signal: AbortSignal.timeout(12e4)
|
|
67
|
-
});
|
|
68
|
-
const data = await r.json().catch(() => ({}));
|
|
69
|
-
if (!r.ok) {
|
|
70
|
-
const error = data.error ?? `HTTP ${r.status}`;
|
|
71
|
-
spinner.warn(`Site import failed: ${error}. Re-run to retry.`);
|
|
72
|
-
return { ok: false, registered: [], error };
|
|
73
|
-
}
|
|
74
|
-
const registered = data.registered ?? [];
|
|
75
|
-
const warnings = data.warnings ?? [];
|
|
76
|
-
const missed = sites.length - registered.length;
|
|
77
|
-
if (sites.length > 0 && registered.length === 0) {
|
|
78
|
-
spinner.fail(
|
|
79
|
-
`Migrated NONE of the ${sites.length} site${sites.length === 1 ? "" : "s"} \u2014 Openship holds :80/:443 and ${sites.length === 1 ? "that hostname is" : "those hostnames are"} NOT being served.`
|
|
80
|
-
);
|
|
81
|
-
for (const w of warnings.slice(0, 8)) console.log(chalk.red(` \u2022 ${w}`));
|
|
82
|
-
const edgeLog = await edgeCrashReason(new LocalExecutor());
|
|
83
|
-
if (edgeLog) {
|
|
84
|
-
console.log(chalk.red(`
|
|
85
|
-
The edge container is not running. Its log says:`));
|
|
86
|
-
console.log(chalk.red(` ${edgeLog}`));
|
|
87
|
-
}
|
|
88
|
-
const back = startUnitHint("nginx");
|
|
89
|
-
console.log(
|
|
90
|
-
chalk.yellow(
|
|
91
|
-
`
|
|
92
|
-
Retry the import with \`openship up\` once the cause above is fixed, or put your
|
|
93
|
-
` + (back ? ` previous proxy back: docker stop ${EDGE_CONTAINER_NAME} && ${back}
|
|
94
|
-
` : ` previous proxy back by stopping ${EDGE_CONTAINER_NAME} and starting it the way
|
|
95
|
-
this host starts services.
|
|
96
|
-
`)
|
|
97
|
-
)
|
|
98
|
-
);
|
|
99
|
-
return { ok: false, registered, error: warnings[0] ?? "no sites were registered" };
|
|
100
|
-
}
|
|
101
|
-
if (missed > 0) {
|
|
102
|
-
spinner.warn(
|
|
103
|
-
`Migrated ${registered.length}/${sites.length} sites \u2014 ${missed} not served (see below).`
|
|
104
|
-
);
|
|
105
|
-
for (const w of warnings.slice(0, 8)) console.log(chalk.yellow(` \u2022 ${w}`));
|
|
106
|
-
return { ok: false, registered, error: `${missed} site(s) not registered` };
|
|
107
|
-
}
|
|
108
|
-
spinner.succeed(
|
|
109
|
-
`Migrated ${registered.length} site${registered.length === 1 ? "" : "s"} into Openship's edge.`
|
|
110
|
-
);
|
|
111
|
-
for (const w of warnings.slice(0, 8)) console.log(chalk.dim(` \u2022 ${w}`));
|
|
112
|
-
return { ok: true, registered };
|
|
113
|
-
} catch (e) {
|
|
114
|
-
const error = e.message;
|
|
115
|
-
spinner.warn(`Site import failed: ${error}. Re-run to retry.`);
|
|
116
|
-
return { ok: false, registered: [], error };
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export {
|
|
121
|
-
waitForApiHealth,
|
|
122
|
-
waitForEdgeRunning,
|
|
123
|
-
importMigratedSites
|
|
124
|
-
};
|