akanjs 3.1.1-rc.7 → 3.1.1-rc.9
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/index.ts +5 -5
- package/package.json +1 -1
- package/types/index.d.ts +5 -5
- package/types/vendor/@akanjs/native/packages/cli/src/api.d.ts +10 -10
- package/types/vendor/@akanjs/native/packages/cli/src/config.d.ts +9 -4
- package/types/vendor/@akanjs/native/packages/cli/src/lib/publish.d.ts +13 -13
- package/types/vendor/@akanjs/native/packages/cli/src/lib/updates.d.ts +22 -12
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.d.ts +5 -0
- package/types/vendor/@akanjs/native/packages/core/src/kernel.d.ts +11 -0
- package/types/vendor/@akanjs/native/plugins/updates/src/desktop.d.ts +8 -1
- package/vendor/@akanjs/native/packages/cli/src/api.ts +12 -12
- package/vendor/@akanjs/native/packages/cli/src/commands/update.ts +4 -9
- package/vendor/@akanjs/native/packages/cli/src/config.ts +9 -4
- package/vendor/@akanjs/native/packages/cli/src/lib/configkeys.ts +10 -1
- package/vendor/@akanjs/native/packages/cli/src/lib/publish.ts +47 -49
- package/vendor/@akanjs/native/packages/cli/src/lib/updates.ts +40 -17
- package/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.ts +20 -9
- package/vendor/@akanjs/native/packages/core/src/kernel.ts +59 -0
- package/vendor/@akanjs/native/packages/core/vectors/updates.json +24 -1
- package/vendor/@akanjs/native/plugins/updates/src/desktop.ts +186 -25
package/index.ts
CHANGED
|
@@ -127,20 +127,20 @@ export interface AkanNativeDeepLinks {
|
|
|
127
127
|
*/
|
|
128
128
|
export interface AkanNativeUpdatesConfig {
|
|
129
129
|
/**
|
|
130
|
-
* A static base URL, https in a release build, with no query: `<url>/<os>-<arch>/<channel
|
|
130
|
+
* A static base URL, https in a release build, with no query: `<url>/<os>-<arch>/<channel>/app.json` (desktop) or
|
|
131
131
|
* `<url>/<platform>/<channel>/<nativeApi>.json` (a phone's web bundle, one envelope per binary generation).
|
|
132
132
|
*/
|
|
133
133
|
url: string;
|
|
134
134
|
/**
|
|
135
|
-
* The keys a
|
|
136
|
-
*
|
|
137
|
-
*
|
|
135
|
+
* The keys a binary trusts, raw 32-byte Ed25519 public keys in base64 (`akan update-keygen` prints one), 1 to 3:
|
|
136
|
+
* the online signing key first, offline spares after it, since a key may revoke only keys listed before it. A desktop
|
|
137
|
+
* app built before protocol v2 trusts the first.
|
|
138
138
|
*/
|
|
139
139
|
publicKeys?: string[];
|
|
140
140
|
/** The one-key form of `publicKeys`, never beside it: a target overriding native.updates' keys keeps its form. */
|
|
141
141
|
publicKey?: string;
|
|
142
142
|
/**
|
|
143
|
-
* keyIds every
|
|
143
|
+
* keyIds every release revokes (`akan update-keygen` prints a key's), kept here so a release published from a
|
|
144
144
|
* fresh checkout still revokes them; `akan publish-update --revoke` starts a revocation. A key may revoke only keys
|
|
145
145
|
* listed before it in publicKeys, so a release is signed with one listed after them.
|
|
146
146
|
*/
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -113,20 +113,20 @@ export interface AkanNativeDeepLinks {
|
|
|
113
113
|
*/
|
|
114
114
|
export interface AkanNativeUpdatesConfig {
|
|
115
115
|
/**
|
|
116
|
-
* A static base URL, https in a release build, with no query: `<url>/<os>-<arch>/<channel
|
|
116
|
+
* A static base URL, https in a release build, with no query: `<url>/<os>-<arch>/<channel>/app.json` (desktop) or
|
|
117
117
|
* `<url>/<platform>/<channel>/<nativeApi>.json` (a phone's web bundle, one envelope per binary generation).
|
|
118
118
|
*/
|
|
119
119
|
url: string;
|
|
120
120
|
/**
|
|
121
|
-
* The keys a
|
|
122
|
-
*
|
|
123
|
-
*
|
|
121
|
+
* The keys a binary trusts, raw 32-byte Ed25519 public keys in base64 (`akan update-keygen` prints one), 1 to 3:
|
|
122
|
+
* the online signing key first, offline spares after it, since a key may revoke only keys listed before it. A desktop
|
|
123
|
+
* app built before protocol v2 trusts the first.
|
|
124
124
|
*/
|
|
125
125
|
publicKeys?: string[];
|
|
126
126
|
/** The one-key form of `publicKeys`, never beside it: a target overriding native.updates' keys keeps its form. */
|
|
127
127
|
publicKey?: string;
|
|
128
128
|
/**
|
|
129
|
-
* keyIds every
|
|
129
|
+
* keyIds every release revokes (`akan update-keygen` prints a key's), kept here so a release published from a
|
|
130
130
|
* fresh checkout still revokes them; `akan publish-update --revoke` starts a revocation. A key may revoke only keys
|
|
131
131
|
* listed before it in publicKeys, so a release is signed with one listed after them.
|
|
132
132
|
*/
|
|
@@ -18,7 +18,7 @@ export type { UpdateEnvelope, UpdateFile, UpdateManifest } from "./lib/updates.t
|
|
|
18
18
|
* A phone's update protocol as the apps run it, for a signer or a server that checks what it publishes or registers:
|
|
19
19
|
* the envelope's verification, the keyId of a public key, and what a verified manifest means to a binary.
|
|
20
20
|
*/
|
|
21
|
-
export { keyIdOf, openEnvelope } from "./lib/updates.ts";
|
|
21
|
+
export { keyIdOf, openEnvelope, verifyManifest } from "./lib/updates.ts";
|
|
22
22
|
export type { AkanNativeConfig, AndroidSigning, DesktopArch, Device, DeviceSelector, DoctorCheck, IosBuild, IosSigning, IosSigningResult, LinuxBuild, LogEvent, MacosBuild, MacosNotarization, MacosSigning, TargetPlatform, WindowsBuild, WindowsSigning, };
|
|
23
23
|
/**
|
|
24
24
|
* The macOS signing and notarization the AKAN_NATIVE_MACOS_* variables name, for a caller that keeps them in its
|
|
@@ -27,7 +27,7 @@ export type { AkanNativeConfig, AndroidSigning, DesktopArch, Device, DeviceSelec
|
|
|
27
27
|
/** The Authenticode settings the AKAN_NATIVE_WINDOWS_* variables name: pass the result as `windows.signing`. */
|
|
28
28
|
export { macosDistributionFromEnv, requestedDistribution, windowsSigningFromEnv };
|
|
29
29
|
/** semver of this API. A caller checks the major before it relies on anything here. */
|
|
30
|
-
export declare const API_VERSION = "0.
|
|
30
|
+
export declare const API_VERSION = "0.13.0";
|
|
31
31
|
export type AkanNativeErrorCode = "CONFIG_INVALID" | "TOOLCHAIN_MISSING" | "WEB_INPUT_INVALID" | "WEB_BUILD_FAILED" | "NATIVE_BUILD_FAILED" | "SIGNING_FAILED" | "DEVICE_FAILED" | "CANCELLED" | "INTERNAL";
|
|
32
32
|
export declare class AkanNativeError extends Error {
|
|
33
33
|
readonly code: AkanNativeErrorCode;
|
|
@@ -159,17 +159,17 @@ export interface PublishCheckOptions extends Pick<TaskOptions, "appDir" | "confi
|
|
|
159
159
|
/** A desktop release's CPU, which names its feed folder: this computer's by default. */
|
|
160
160
|
arch?: DesktopArch;
|
|
161
161
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
162
|
+
* keyIds of updates.publicKeys the release starts revoking, beside updates.revokedKeys and what the channel's releases
|
|
163
|
+
* revoke. It is signed with a key listed after every key it revokes.
|
|
164
164
|
*/
|
|
165
165
|
revoke?: string[];
|
|
166
|
-
/** A
|
|
166
|
+
/** A release that revokes a key: apps compare it with their own build instead of the running release. */
|
|
167
167
|
resetSequence?: boolean;
|
|
168
168
|
}
|
|
169
169
|
/**
|
|
170
170
|
* What publishUpdate() refuses before it builds, without building (CONFIG_INVALID): no updates settings, a channel no
|
|
171
171
|
* app could be configured for, no signing key on this machine or another app's, a desktop release whose server
|
|
172
|
-
* presence is not the channel's previous release's, and a
|
|
172
|
+
* presence is not the channel's previous release's, and a release whose revocations no app would take. For a
|
|
173
173
|
* caller with a long build of its own before publishUpdate.
|
|
174
174
|
*/
|
|
175
175
|
export declare function checkPublishUpdate(options: PublishCheckOptions): {
|
|
@@ -177,8 +177,8 @@ export declare function checkPublishUpdate(options: PublishCheckOptions): {
|
|
|
177
177
|
out: string;
|
|
178
178
|
};
|
|
179
179
|
/**
|
|
180
|
-
* A signed release for the updates plugin (UP-1, UP-2): a release build, then
|
|
181
|
-
*
|
|
180
|
+
* A signed release for the updates plugin (UP-1, UP-2): a release build, then its envelope and its files under `out`
|
|
181
|
+
* (default <appDir>/.akan/native/updates), signed with the key updateKeygen() made.
|
|
182
182
|
*/
|
|
183
183
|
export declare function publishUpdate(options: TaskOptions & {
|
|
184
184
|
platform: Exclude<TargetPlatform, "web">;
|
|
@@ -190,9 +190,9 @@ export declare function publishUpdate(options: TaskOptions & {
|
|
|
190
190
|
windows?: Pick<WindowsBuild, "signing">;
|
|
191
191
|
/** A desktop release's CPU, of the same OS: an x64 release from an arm64 machine. Default this computer's. */
|
|
192
192
|
arch?: DesktopArch;
|
|
193
|
-
/**
|
|
193
|
+
/** keyIds of updates.publicKeys the release starts revoking (PublishCheckOptions.revoke). */
|
|
194
194
|
revoke?: string[];
|
|
195
|
-
/** A
|
|
195
|
+
/** A release that revokes a key: apps compare it with their own build instead of the running release. */
|
|
196
196
|
resetSequence?: boolean;
|
|
197
197
|
}): Promise<PublishResult>;
|
|
198
198
|
/**
|
|
@@ -115,17 +115,17 @@ export interface AkanNativeConfig {
|
|
|
115
115
|
/**
|
|
116
116
|
* Over-the-air updates (UP-2 web bundles on iOS / Android, UP-1 app updates on macOS), used by
|
|
117
117
|
* @akanjs/native/plugins/updates. `akan-native update keygen` makes the signing key and prints its public key;
|
|
118
|
-
* `akan-native update publish <platform>` writes signed releases for `url`. `publicKeys` lists the keys
|
|
118
|
+
* `akan-native update publish <platform>` writes signed releases for `url`. `publicKeys` lists the keys an app
|
|
119
119
|
* trusts, the online signing key first and offline spares after (a key revokes only keys before it); `publicKey` is
|
|
120
|
-
* the one-key form, and a desktop app trusts the first. `report.url` is where a phone posts
|
|
121
|
-
* release, at its next launch or return to the foreground.
|
|
120
|
+
* the one-key form, and a desktop app built before protocol v2 trusts the first. `report.url` is where a phone posts
|
|
121
|
+
* what became of each release, at its next launch or return to the foreground.
|
|
122
122
|
*/
|
|
123
123
|
updates?: {
|
|
124
124
|
url: string;
|
|
125
125
|
publicKey?: string;
|
|
126
126
|
publicKeys?: string[];
|
|
127
127
|
/**
|
|
128
|
-
* keyIds every
|
|
128
|
+
* keyIds every release revokes (`update keygen` prints a key's), kept here so a release published from a fresh
|
|
129
129
|
* folder still revokes them; `update publish --revoke` starts a revocation. A key may revoke only keys listed
|
|
130
130
|
* before it in publicKeys, so a release is signed with one listed after them.
|
|
131
131
|
*/
|
|
@@ -135,6 +135,11 @@ export interface AkanNativeConfig {
|
|
|
135
135
|
report?: {
|
|
136
136
|
url: string;
|
|
137
137
|
};
|
|
138
|
+
/**
|
|
139
|
+
* The release target a desktop binary is built for: its manifests name it and the app takes only its own, so a
|
|
140
|
+
* release signed for one target cannot be served to another's apps. akan sets the native target's name.
|
|
141
|
+
*/
|
|
142
|
+
target?: string;
|
|
138
143
|
};
|
|
139
144
|
/** Links that open the app, delivered through the app plugin's urlOpen (and getLaunchUrl). */
|
|
140
145
|
deepLinks?: {
|
|
@@ -5,7 +5,7 @@ export interface PublishedRelease {
|
|
|
5
5
|
/** `<out>/<os>-<arch>` for a desktop app, `<out>/<platform>` for a phone's web bundle. */
|
|
6
6
|
dir: string;
|
|
7
7
|
manifest: UpdateManifest;
|
|
8
|
-
/** The
|
|
8
|
+
/** The envelope installed apps read: a desktop's `<dir>/<channel>/app.json`, a phone's `<dir>/<channel>/<nativeApi>.json`. */
|
|
9
9
|
file: string;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
@@ -22,23 +22,19 @@ export declare function assertServerOfChannel(config: {
|
|
|
22
22
|
server?: unknown;
|
|
23
23
|
};
|
|
24
24
|
}, platform: ReleasePlatform, out: string, channel: string, arch?: DesktopArch): void;
|
|
25
|
-
/**
|
|
26
|
-
* Refuses before the build a release that could not be signed: no key on this machine, another app's, or for a desktop
|
|
27
|
-
* app one the app does not trust (it trusts the first of updates.publicKeys).
|
|
28
|
-
*/
|
|
25
|
+
/** Refuses before the build a release that could not be signed: no key on this machine, or another app's. */
|
|
29
26
|
export declare function assertSigningKey(config: {
|
|
30
27
|
app: {
|
|
31
28
|
id: string;
|
|
32
29
|
};
|
|
33
30
|
updates?: {
|
|
34
31
|
publicKeys: string[];
|
|
35
|
-
revokedKeys?: readonly string[];
|
|
36
32
|
} | null;
|
|
37
|
-
}
|
|
33
|
+
}): void;
|
|
38
34
|
export interface RevocationRequest {
|
|
39
35
|
/** keyIds of updates.publicKeys this release starts revoking (`update publish --revoke`). */
|
|
40
36
|
revoke?: readonly string[];
|
|
41
|
-
/** With a revocation,
|
|
37
|
+
/** With a revocation, an app compares the release with its own build instead of the running release. */
|
|
42
38
|
resetSequence?: boolean;
|
|
43
39
|
}
|
|
44
40
|
interface RevocationConfig {
|
|
@@ -51,16 +47,20 @@ interface RevocationConfig {
|
|
|
51
47
|
} | null;
|
|
52
48
|
}
|
|
53
49
|
/**
|
|
54
|
-
* The revokeKeys and resetSequence of a
|
|
55
|
-
* releases revoke, and `revoke`, since
|
|
50
|
+
* The revokeKeys and resetSequence of a release of `channel` under `out`: updates.revokedKeys, what the channel's
|
|
51
|
+
* releases revoke, and `revoke`, since an app that never saw a revocation (a new install, cleared data) learns it only
|
|
56
52
|
* from a later manifest. Refuses a `revoke` the ring does not hold, more keys than a manifest may revoke, a reset that
|
|
57
|
-
* revokes nothing, and a signing key the release revokes or that is listed before a key it revokes: every
|
|
53
|
+
* revokes nothing, and a signing key the release revokes or that is listed before a key it revokes: every app would
|
|
58
54
|
* refuse that manifest, since a key may revoke only keys listed before it.
|
|
59
55
|
*/
|
|
60
|
-
export declare function releaseRevocations(config: RevocationConfig, platform: ReleasePlatform, out: string, channel: string, { revoke, resetSequence }?: RevocationRequest): {
|
|
56
|
+
export declare function releaseRevocations(config: RevocationConfig, platform: ReleasePlatform, out: string, channel: string, { revoke, resetSequence }?: RevocationRequest, arch?: DesktopArch): {
|
|
61
57
|
revokeKeys: string[];
|
|
62
58
|
resetSequence: boolean;
|
|
63
59
|
};
|
|
64
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Writes the release of `artifact` (the app a release build made) and its envelope under `out`. A desktop release also
|
|
62
|
+
* gets the v1 pair when signed with the first key, the only one an app built before protocol v2 trusts: that is how
|
|
63
|
+
* such an app takes a binary that reads envelopes.
|
|
64
|
+
*/
|
|
65
65
|
export declare function publishRelease(ctx: BuildContext, platform: ReleasePlatform, artifact: string, out: string, channel: string, request?: RevocationRequest): Promise<PublishedRelease>;
|
|
66
66
|
export {};
|
|
@@ -3,17 +3,22 @@ export interface UpdatesConfig {
|
|
|
3
3
|
/** Base URL of the update files, e.g. "https://example.com/updates". http:// only for localhost / 10.0.2.2 in dev builds. */
|
|
4
4
|
url: string;
|
|
5
5
|
/**
|
|
6
|
-
* Raw 32-byte Ed25519 public keys, base64 (`akan-native update keygen` prints one): the keys a
|
|
6
|
+
* Raw 32-byte Ed25519 public keys, base64 (`akan-native update keygen` prints one): the keys a binary trusts, the
|
|
7
7
|
* online signing key first and offline spares after it, since a key may revoke only keys listed before it. A desktop
|
|
8
|
-
* app trusts the first.
|
|
8
|
+
* app built before protocol v2 trusts the first.
|
|
9
9
|
*/
|
|
10
10
|
publicKeys: string[];
|
|
11
11
|
/**
|
|
12
|
-
* keyIds every
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* keyIds every release revokes, kept in the config so a release published from another folder (a fresh CI checkout)
|
|
13
|
+
* still revokes them. `akan-native update publish --revoke` starts a revocation. A build trusts none of them, though
|
|
14
|
+
* publicKeys still lists them.
|
|
15
15
|
*/
|
|
16
16
|
revokedKeys: string[];
|
|
17
|
+
/**
|
|
18
|
+
* The release target a desktop binary is built for (akan's native target): its manifests name it and the app takes
|
|
19
|
+
* only its own, so a release signed for one target cannot be served to another's apps. null: the manifest names none.
|
|
20
|
+
*/
|
|
21
|
+
target: string | null;
|
|
17
22
|
/** Manifest name under <platform>/. Default "production". */
|
|
18
23
|
channel: string;
|
|
19
24
|
/** How long a newly applied bundle has to call notifyReady() before it is rolled back, ms. Default 10000. */
|
|
@@ -31,7 +36,7 @@ export type DesktopArch = "arm64" | "x64";
|
|
|
31
36
|
/** The CPU of the desktop apps this machine builds (cargo and bun build for the host). */
|
|
32
37
|
export declare function hostArch(): DesktopArch;
|
|
33
38
|
export interface UpdateManifest {
|
|
34
|
-
/** 2 for a phone's web bundle,
|
|
39
|
+
/** 2 for a release in an UpdateEnvelope (a phone's web bundle, a desktop app); 1 for a desktop app's v1 pair. */
|
|
35
40
|
schema: 1 | 2;
|
|
36
41
|
kind: "web" | "app";
|
|
37
42
|
app: string;
|
|
@@ -67,12 +72,17 @@ export interface UpdateManifest {
|
|
|
67
72
|
}[];
|
|
68
73
|
/** App updates: whether the app carries a server; an installed app refuses a release that differs from itself. */
|
|
69
74
|
server?: boolean;
|
|
70
|
-
/**
|
|
75
|
+
/** App updates of schema 2: updates.target of the apps the release is for; absent when that is null. */
|
|
76
|
+
target?: string;
|
|
77
|
+
/** Schema 2: keyIds the app stops trusting for good; each listed before the signer's key in its updates.publicKeys. */
|
|
71
78
|
revokeKeys?: string[];
|
|
72
|
-
/**
|
|
79
|
+
/** Schema 2: with a new revocation, compare this release with the binary's own bundle instead of the running one. */
|
|
73
80
|
resetSequence?: boolean;
|
|
74
81
|
}
|
|
75
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* A phone's `<platform>/<channel>/<nativeApi>.json` or a desktop app's `<os>-<arch>/<channel>/app.json`: one object, so
|
|
84
|
+
* a new manifest never meets an old signature.
|
|
85
|
+
*/
|
|
76
86
|
export interface UpdateEnvelope {
|
|
77
87
|
/** The manifest's exact bytes, base64. */
|
|
78
88
|
manifest: string;
|
|
@@ -146,10 +156,10 @@ export declare function updatesResource(updates: UpdatesConfig, app: {
|
|
|
146
156
|
version: string;
|
|
147
157
|
}, platform: Platform, nativeApi: string | undefined, dev: boolean, embeddedSequence?: number): string;
|
|
148
158
|
/**
|
|
149
|
-
* The keys a
|
|
150
|
-
*
|
|
159
|
+
* The keys a build trusts: updates.publicKeys without the revoked ones, so a fresh install trusts none of them before
|
|
160
|
+
* its first release tells it. A manifest that revokes a key the binary does not hold is still taken.
|
|
151
161
|
*/
|
|
152
|
-
export declare const
|
|
162
|
+
export declare const updateRing: (updates: Pick<UpdatesConfig, "publicKeys" | "revokedKeys">) => string[];
|
|
153
163
|
/**
|
|
154
164
|
* updates.json of a phone build, and the same facts in the build's bundle.json: a signer that registers the store build
|
|
155
165
|
* checks the binary reads its URL and keys, and takes `embeddedSequence` as the floor every release must pass.
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { BuildContext } from "../lib/prepare.ts";
|
|
2
2
|
import { type UpdateManifest } from "../lib/updates.ts";
|
|
3
3
|
import { type DesktopOs } from "./desktop.ts";
|
|
4
|
+
/**
|
|
5
|
+
* The release of `channel` in `dir`: the manifest of its envelope, else the v1 `<channel>.json` of a folder published
|
|
6
|
+
* before protocol v2. Read unverified, as the publisher's own folder.
|
|
7
|
+
*/
|
|
8
|
+
export declare function publishedApp(dir: string, channel: string): Partial<UpdateManifest> | null;
|
|
4
9
|
/**
|
|
5
10
|
* An installed app refuses a release whose server presence is not its own (plugins/updates): published, this one would
|
|
6
11
|
* be refused by every app the channel reached, and so would every release after it. A manifest from before the field
|
|
@@ -146,8 +146,19 @@ export declare function updateDecision(input: UpdateDecisionInput): UpdateDecisi
|
|
|
146
146
|
export declare const updateDecisionWire: (decision: UpdateDecision) => string;
|
|
147
147
|
/** The v2 envelope of a channel for one native API: one file per binary generation, so each takes its own fixes. */
|
|
148
148
|
export declare const updateManifestUrl: (url: string, platform: string, channel: string, nativeApi: string) => string;
|
|
149
|
+
/**
|
|
150
|
+
* A desktop app's v2 envelope of a channel: the whole app is one release per OS and CPU, so one file. `app` is a
|
|
151
|
+
* reserved channel name, since `<os>-<arch>/app/` holds the archives.
|
|
152
|
+
*/
|
|
153
|
+
export declare const appManifestUrl: (url: string, os: string, arch: string, channel: string) => string;
|
|
149
154
|
/** An envelope's signer or a revokeKeys entry: the first 8 bytes of the raw public key's SHA-256, in hex. */
|
|
150
155
|
export declare const isUpdateKeyId: (s: string) => boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Whether a base64 string is an Ed25519 public key a release may be signed for: strict base64 of 32 bytes, the
|
|
158
|
+
* canonical encoding of a curve point (RFC 8032 §5.1.3, y < p and no negative zero), not of small order. A small-order
|
|
159
|
+
* key verifies signatures nobody made with a private key, so a config listing one would trust forged releases.
|
|
160
|
+
*/
|
|
161
|
+
export declare function isUpdatePublicKey(key: string): boolean;
|
|
151
162
|
/** The most keys a manifest may revoke: every host refuses a longer revokeKeys. */
|
|
152
163
|
export declare const MAX_REVOKE_KEYS = 16;
|
|
153
164
|
/** The largest manifest an envelope may carry, in bytes. */
|
|
@@ -7,7 +7,14 @@ export interface UpdatesConfig {
|
|
|
7
7
|
nativeApi: string | null;
|
|
8
8
|
embeddedSequence: number;
|
|
9
9
|
url: string;
|
|
10
|
-
|
|
10
|
+
/** 2: envelopes signed by any key of `publicKeys`; absent, the v1 pair signed by `publicKey`. */
|
|
11
|
+
protocol?: number;
|
|
12
|
+
/** v2: the keys of updates.publicKeys this build trusts, revoked ones left out. */
|
|
13
|
+
publicKeys?: string[];
|
|
14
|
+
/** The first of updates.publicKeys, the one key v1 trusts. */
|
|
15
|
+
publicKey?: string;
|
|
16
|
+
/** v2: updates.target, which a release must name; absent, it must name none. */
|
|
17
|
+
target?: string;
|
|
11
18
|
channel: string;
|
|
12
19
|
readyTimeout: number;
|
|
13
20
|
}
|
|
@@ -76,7 +76,7 @@ export type { UpdateEnvelope, UpdateFile, UpdateManifest } from "./lib/updates.t
|
|
|
76
76
|
* A phone's update protocol as the apps run it, for a signer or a server that checks what it publishes or registers:
|
|
77
77
|
* the envelope's verification, the keyId of a public key, and what a verified manifest means to a binary.
|
|
78
78
|
*/
|
|
79
|
-
export { keyIdOf, openEnvelope } from "./lib/updates.ts";
|
|
79
|
+
export { keyIdOf, openEnvelope, verifyManifest } from "./lib/updates.ts";
|
|
80
80
|
export type {
|
|
81
81
|
AkanNativeConfig,
|
|
82
82
|
AndroidSigning,
|
|
@@ -104,7 +104,7 @@ export type {
|
|
|
104
104
|
export { macosDistributionFromEnv, requestedDistribution, windowsSigningFromEnv };
|
|
105
105
|
|
|
106
106
|
/** semver of this API. A caller checks the major before it relies on anything here. */
|
|
107
|
-
export const API_VERSION = "0.
|
|
107
|
+
export const API_VERSION = "0.13.0";
|
|
108
108
|
|
|
109
109
|
export type AkanNativeErrorCode =
|
|
110
110
|
| "CONFIG_INVALID"
|
|
@@ -326,18 +326,18 @@ export interface PublishCheckOptions extends Pick<TaskOptions, "appDir" | "confi
|
|
|
326
326
|
/** A desktop release's CPU, which names its feed folder: this computer's by default. */
|
|
327
327
|
arch?: DesktopArch;
|
|
328
328
|
/**
|
|
329
|
-
*
|
|
330
|
-
*
|
|
329
|
+
* keyIds of updates.publicKeys the release starts revoking, beside updates.revokedKeys and what the channel's releases
|
|
330
|
+
* revoke. It is signed with a key listed after every key it revokes.
|
|
331
331
|
*/
|
|
332
332
|
revoke?: string[];
|
|
333
|
-
/** A
|
|
333
|
+
/** A release that revokes a key: apps compare it with their own build instead of the running release. */
|
|
334
334
|
resetSequence?: boolean;
|
|
335
335
|
}
|
|
336
336
|
|
|
337
337
|
/**
|
|
338
338
|
* What publishUpdate() refuses before it builds, without building (CONFIG_INVALID): no updates settings, a channel no
|
|
339
339
|
* app could be configured for, no signing key on this machine or another app's, a desktop release whose server
|
|
340
|
-
* presence is not the channel's previous release's, and a
|
|
340
|
+
* presence is not the channel's previous release's, and a release whose revocations no app would take. For a
|
|
341
341
|
* caller with a long build of its own before publishUpdate.
|
|
342
342
|
*/
|
|
343
343
|
export function checkPublishUpdate(options: PublishCheckOptions): { channel: string; out: string } {
|
|
@@ -352,8 +352,8 @@ export function checkPublishUpdate(options: PublishCheckOptions): { channel: str
|
|
|
352
352
|
try {
|
|
353
353
|
if (options.channel !== undefined) assertChannel(options.channel);
|
|
354
354
|
const target = { app: options.config.app, updates };
|
|
355
|
-
assertSigningKey(target
|
|
356
|
-
releaseRevocations(target, options.platform, out, channel, options);
|
|
355
|
+
assertSigningKey(target);
|
|
356
|
+
releaseRevocations(target, options.platform, out, channel, options, options.arch);
|
|
357
357
|
const server = options.server ?? !!options.config.desktop?.server;
|
|
358
358
|
assertServerOfChannel({ desktop: server ? { server } : {} }, options.platform, out, channel, options.arch);
|
|
359
359
|
} catch (error) {
|
|
@@ -363,8 +363,8 @@ export function checkPublishUpdate(options: PublishCheckOptions): { channel: str
|
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
/**
|
|
366
|
-
* A signed release for the updates plugin (UP-1, UP-2): a release build, then
|
|
367
|
-
*
|
|
366
|
+
* A signed release for the updates plugin (UP-1, UP-2): a release build, then its envelope and its files under `out`
|
|
367
|
+
* (default <appDir>/.akan/native/updates), signed with the key updateKeygen() made.
|
|
368
368
|
*/
|
|
369
369
|
export function publishUpdate(
|
|
370
370
|
options: TaskOptions & {
|
|
@@ -377,9 +377,9 @@ export function publishUpdate(
|
|
|
377
377
|
windows?: Pick<WindowsBuild, "signing">;
|
|
378
378
|
/** A desktop release's CPU, of the same OS: an x64 release from an arm64 machine. Default this computer's. */
|
|
379
379
|
arch?: DesktopArch;
|
|
380
|
-
/**
|
|
380
|
+
/** keyIds of updates.publicKeys the release starts revoking (PublishCheckOptions.revoke). */
|
|
381
381
|
revoke?: string[];
|
|
382
|
-
/** A
|
|
382
|
+
/** A release that revokes a key: apps compare it with their own build instead of the running release. */
|
|
383
383
|
resetSequence?: boolean;
|
|
384
384
|
},
|
|
385
385
|
): Promise<PublishResult> {
|
|
@@ -64,16 +64,11 @@ async function publish(args: ParsedArgs, request: RevocationRequest): Promise<nu
|
|
|
64
64
|
const requested = stringFlag(args, "channel");
|
|
65
65
|
if (requested !== undefined) assertChannel(requested);
|
|
66
66
|
const project = await loadProject(findAppDir(stringFlag(args, "app") ?? process.cwd()));
|
|
67
|
-
assertSigningKey(project.config
|
|
67
|
+
assertSigningKey(project.config);
|
|
68
68
|
const planned = requested ?? project.config.updates?.channel ?? "production";
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
outDir(args, project.appDir),
|
|
73
|
-
planned,
|
|
74
|
-
desktopArch(platform, stringFlag(args, "arch") as DesktopArch | undefined),
|
|
75
|
-
);
|
|
76
|
-
releaseRevocations(project.config, platform, outDir(args, project.appDir), planned, request);
|
|
69
|
+
const arch = desktopArch(platform, stringFlag(args, "arch") as DesktopArch | undefined);
|
|
70
|
+
assertServerOfChannel(project.config, platform, outDir(args, project.appDir), planned, arch);
|
|
71
|
+
releaseRevocations(project.config, platform, outDir(args, project.appDir), planned, request, arch);
|
|
77
72
|
const { ctx, artifact } = await buildFromArgs(
|
|
78
73
|
{ positional: [platform], flags: args.flags },
|
|
79
74
|
{ mode: "production", profile: "release" },
|
|
@@ -115,17 +115,17 @@ export interface AkanNativeConfig {
|
|
|
115
115
|
/**
|
|
116
116
|
* Over-the-air updates (UP-2 web bundles on iOS / Android, UP-1 app updates on macOS), used by
|
|
117
117
|
* @akanjs/native/plugins/updates. `akan-native update keygen` makes the signing key and prints its public key;
|
|
118
|
-
* `akan-native update publish <platform>` writes signed releases for `url`. `publicKeys` lists the keys
|
|
118
|
+
* `akan-native update publish <platform>` writes signed releases for `url`. `publicKeys` lists the keys an app
|
|
119
119
|
* trusts, the online signing key first and offline spares after (a key revokes only keys before it); `publicKey` is
|
|
120
|
-
* the one-key form, and a desktop app trusts the first. `report.url` is where a phone posts
|
|
121
|
-
* release, at its next launch or return to the foreground.
|
|
120
|
+
* the one-key form, and a desktop app built before protocol v2 trusts the first. `report.url` is where a phone posts
|
|
121
|
+
* what became of each release, at its next launch or return to the foreground.
|
|
122
122
|
*/
|
|
123
123
|
updates?: {
|
|
124
124
|
url: string;
|
|
125
125
|
publicKey?: string;
|
|
126
126
|
publicKeys?: string[];
|
|
127
127
|
/**
|
|
128
|
-
* keyIds every
|
|
128
|
+
* keyIds every release revokes (`update keygen` prints a key's), kept here so a release published from a fresh
|
|
129
129
|
* folder still revokes them; `update publish --revoke` starts a revocation. A key may revoke only keys listed
|
|
130
130
|
* before it in publicKeys, so a release is signed with one listed after them.
|
|
131
131
|
*/
|
|
@@ -133,6 +133,11 @@ export interface AkanNativeConfig {
|
|
|
133
133
|
channel?: string;
|
|
134
134
|
readyTimeout?: number;
|
|
135
135
|
report?: { url: string };
|
|
136
|
+
/**
|
|
137
|
+
* The release target a desktop binary is built for: its manifests name it and the app takes only its own, so a
|
|
138
|
+
* release signed for one target cannot be served to another's apps. akan sets the native target's name.
|
|
139
|
+
*/
|
|
140
|
+
target?: string;
|
|
136
141
|
};
|
|
137
142
|
/** Links that open the app, delivered through the app plugin's urlOpen (and getLaunchUrl). */
|
|
138
143
|
deepLinks?: {
|
|
@@ -20,7 +20,16 @@ const KNOWN: Shape = {
|
|
|
20
20
|
usageDescriptions: true,
|
|
21
21
|
privacy: { tracking: true, trackingDomains: true, collectedDataTypes: true, accessedApis: true },
|
|
22
22
|
permissions: { camera: true, microphone: true, location: true },
|
|
23
|
-
updates: {
|
|
23
|
+
updates: {
|
|
24
|
+
url: true,
|
|
25
|
+
publicKey: true,
|
|
26
|
+
publicKeys: true,
|
|
27
|
+
revokedKeys: true,
|
|
28
|
+
channel: true,
|
|
29
|
+
readyTimeout: true,
|
|
30
|
+
report: { url: true },
|
|
31
|
+
target: true,
|
|
32
|
+
},
|
|
24
33
|
deepLinks: { schemes: true, domains: { "[]": { host: true, pathPrefixes: true } } },
|
|
25
34
|
native: {
|
|
26
35
|
ios: { infoPlist: true, entitlements: true },
|