@hraness/ghostget 0.17.5 → 0.18.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/CHANGELOG.md +25 -0
- package/README.md +16 -9
- package/dist/apple-photos-client.js +1 -1
- package/dist/beeper-client.js +1 -1
- package/dist/{index-pf74yjs2.js → index-9wca02er.js} +1 -1
- package/docs/control-panel.md +147 -0
- package/package.json +47 -7
- package/skills/ghostget/SKILL.md +3 -1
- package/skills/ghostget/references/control-panel.md +43 -0
- package/skills/ghostget/references/install.md +5 -5
- package/skills/ghostget/references/linkedin-adapter.md +17 -3
- package/skills/ghostget/references/platform-patterns.md +1 -1
- package/src/assets/adapters/linkedin/wrench-web-adapter.json +1 -1
- package/src/auth.ts +35 -1
- package/src/beeper-client-types.ts +1 -1
- package/src/cli.ts +18 -0
- package/src/confirmed-write-platform.ts +16 -1
- package/src/control/account-revision.ts +16 -0
- package/src/control/activity.ts +104 -0
- package/src/control/approval-broker.ts +59 -0
- package/src/control/approval-client.ts +49 -0
- package/src/control/bundled-interfaces.ts +20 -0
- package/src/control/cli.ts +20 -0
- package/src/control/connections.ts +87 -0
- package/src/control/credential-helper.ts +152 -0
- package/src/control/helper.ts +79 -0
- package/src/control/interface-cli.ts +22 -0
- package/src/control/interface-json.ts +94 -0
- package/src/control/interface-schema.ts +120 -0
- package/src/control/interfaces.ts +438 -0
- package/src/control/protocol.ts +182 -0
- package/src/control/service.ts +104 -0
- package/src/control/validation.ts +103 -0
- package/src/control/vault.ts +105 -0
- package/src/control/web-gateway.ts +62 -0
- package/src/control/web-policy.ts +56 -0
- package/src/ghostget.ts +2 -0
- package/src/messaging-runtime.ts +3 -0
- package/src/oauth-google.ts +11 -5
- package/src/omni-runtime.ts +18 -3
- package/src/operation-permission-store.ts +92 -0
- package/src/operation-permission.ts +308 -0
- package/src/pinned-https.ts +5 -0
- package/src/provider-http.ts +11 -3
- package/src/provider-plugin-contract-identity.ts +2 -2
- package/src/provider-plugin-import-analysis.ts +52 -0
- package/src/provider-plugin-module-analysis.ts +21 -1
- package/src/provider-plugin-registry.ts +4 -8
- package/src/provider-plugin.ts +4 -8
- package/src/providers/linkedin-web-contact.ts +237 -21
- package/src/read-client.ts +12 -2
- package/src/runtime.ts +81 -9
- package/src/state-helper.ts +2 -0
- package/src/storage.ts +71 -1
- package/src/usage.ts +6 -0
- package/src/version.ts +1 -1
package/src/storage.ts
CHANGED
|
@@ -101,11 +101,13 @@ const stateDirectoryNames = [
|
|
|
101
101
|
"auth",
|
|
102
102
|
"browser-snapshots",
|
|
103
103
|
"captures",
|
|
104
|
+
"control",
|
|
104
105
|
"derivations",
|
|
105
106
|
"idempotency",
|
|
106
107
|
"linked-device-stores",
|
|
107
108
|
"messaging",
|
|
108
109
|
"omni-read-projections",
|
|
110
|
+
"operation-permissions",
|
|
109
111
|
"plan-assets",
|
|
110
112
|
"plans",
|
|
111
113
|
"provider-plugin-state",
|
|
@@ -1158,7 +1160,7 @@ function validateStateRoot(root: string): StateRootRecord {
|
|
|
1158
1160
|
return { claimed, creationAnchor: null, identity: { device: stats.dev.toString(), inode: stats.ino.toString() } };
|
|
1159
1161
|
}
|
|
1160
1162
|
|
|
1161
|
-
|
|
1163
|
+
function selectStateHome(environment: Readonly<Record<string, string | undefined>>): string {
|
|
1162
1164
|
const configuredRoots = [
|
|
1163
1165
|
["GHOSTGET_STATE_HOME", environment.GHOSTGET_STATE_HOME],
|
|
1164
1166
|
["WRENCH_STATE_HOME", environment.WRENCH_STATE_HOME],
|
|
@@ -1215,6 +1217,74 @@ export function ghostgetStateHome(environment: Readonly<Record<string, string |
|
|
|
1215
1217
|
if (forbiddenRoots.has(root) || isWithinPath(ghostgetSourcePackageRoot, root)) {
|
|
1216
1218
|
throw new Error(`GHOSTGET_STATE_HOME must be a dedicated child directory, not a filesystem, home, temporary, repository, or shared data root: ${root}`);
|
|
1217
1219
|
}
|
|
1220
|
+
return root;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
/**
|
|
1224
|
+
* Inspect only whether an optional policy may exist, without adopting a state
|
|
1225
|
+
* root. CLI validation and local file inputs must not claim or register state.
|
|
1226
|
+
* A present file still requires the ordinary inode-bound private state reader.
|
|
1227
|
+
*/
|
|
1228
|
+
export function privateStateFilesMayExist(
|
|
1229
|
+
collection: typeof stateDirectoryNames[number],
|
|
1230
|
+
fileNames: readonly string[],
|
|
1231
|
+
environment: Readonly<Record<string, string | undefined>> = process.env,
|
|
1232
|
+
): boolean {
|
|
1233
|
+
if (!stateDirectoryNames.includes(collection) || fileNames.length < 1 || fileNames.length > 8
|
|
1234
|
+
|| fileNames.some(name => !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/u.test(name))) {
|
|
1235
|
+
throw new Error("optional private state file selection is invalid");
|
|
1236
|
+
}
|
|
1237
|
+
const root = selectStateHome(environment);
|
|
1238
|
+
const inspect = (path: string): BigIntStats | null => {
|
|
1239
|
+
try { return lstatSync(path, { bigint: true }); }
|
|
1240
|
+
catch (error) { if (hasCode(error, "ENOENT")) return null; throw error; }
|
|
1241
|
+
};
|
|
1242
|
+
const inspectDirectory = (path: string): BigIntStats | null => {
|
|
1243
|
+
const stats = inspect(path);
|
|
1244
|
+
if (stats !== null && (!stats.isDirectory() || stats.isSymbolicLink()
|
|
1245
|
+
|| !ownedByCurrentUser(stats) || (stats.mode & 0o777n) !== 0o700n)) {
|
|
1246
|
+
throw new Error("optional private state directory is unsafe");
|
|
1247
|
+
}
|
|
1248
|
+
return stats;
|
|
1249
|
+
};
|
|
1250
|
+
const assertUnchanged = (path: string, before: BigIntStats | null): void => {
|
|
1251
|
+
const after = inspect(path);
|
|
1252
|
+
if (before === null ? after !== null : after === null
|
|
1253
|
+
|| before.dev !== after.dev || before.ino !== after.ino
|
|
1254
|
+
|| before.mode !== after.mode || before.uid !== after.uid
|
|
1255
|
+
|| before.ctimeNs !== after.ctimeNs || before.mtimeNs !== after.mtimeNs) {
|
|
1256
|
+
throw new Error("optional private state changed during inspection");
|
|
1257
|
+
}
|
|
1258
|
+
};
|
|
1259
|
+
if (knownStateRoots.has(root)) assertStateRootIdentity(root);
|
|
1260
|
+
const rootBefore = inspectDirectory(root);
|
|
1261
|
+
// A missing root is observed from its existing, owned creation anchor; no
|
|
1262
|
+
// directory, mode, marker, or process-local state registration is changed.
|
|
1263
|
+
const anchor = rootBefore === null ? findCreationAnchor(root).path : null;
|
|
1264
|
+
const anchorBefore = anchor === null ? null : inspect(anchor);
|
|
1265
|
+
const markerPath = join(root, stateMarkerName);
|
|
1266
|
+
const markerBefore = inspect(markerPath);
|
|
1267
|
+
if (markerBefore !== null) readStateMarker(markerPath);
|
|
1268
|
+
else if (rootBefore !== null && !hasGhostgetPathIdentity(root)) {
|
|
1269
|
+
throw new Error("optional private state root does not identify dedicated Ghostget state");
|
|
1270
|
+
}
|
|
1271
|
+
const directory = join(root, collection);
|
|
1272
|
+
const directoryBefore = inspectDirectory(directory);
|
|
1273
|
+
let present = false;
|
|
1274
|
+
for (const name of fileNames) {
|
|
1275
|
+
if (inspect(join(directory, name)) !== null) present = true;
|
|
1276
|
+
}
|
|
1277
|
+
if (selectStateHome(environment) !== root) throw new Error("optional private state root selection changed");
|
|
1278
|
+
assertUnchanged(directory, directoryBefore);
|
|
1279
|
+
assertUnchanged(markerPath, markerBefore);
|
|
1280
|
+
assertUnchanged(root, rootBefore);
|
|
1281
|
+
if (anchor !== null) assertUnchanged(anchor, anchorBefore);
|
|
1282
|
+
if (knownStateRoots.has(root)) assertStateRootIdentity(root);
|
|
1283
|
+
return present;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
export function ghostgetStateHome(environment: Readonly<Record<string, string | undefined>> = process.env): string {
|
|
1287
|
+
const root = selectStateHome(environment);
|
|
1218
1288
|
const inspected = validateStateRoot(root);
|
|
1219
1289
|
const remembered = knownStateRoots.get(root);
|
|
1220
1290
|
if (remembered !== undefined) {
|
package/src/usage.ts
CHANGED
|
@@ -30,6 +30,12 @@ export const ghostgetUsage = `Usage:
|
|
|
30
30
|
ghostget transcriber setup --engine whisper-cpp --model <file> [media-options]
|
|
31
31
|
ghostget doctor [--json] Check capture, media, auth, and action dependencies
|
|
32
32
|
ghostget capabilities [adapter] [--json] List installed semantic capabilities
|
|
33
|
+
ghostget web request <https-url> [--method GET|HEAD]
|
|
34
|
+
Retrieve public text through native web rules and approvals
|
|
35
|
+
ghostget interface list List user and imported OpenAPI drafts
|
|
36
|
+
ghostget interface export [adapter] Export installed semantic interfaces as OpenAPI
|
|
37
|
+
ghostget interface import <openapi.json> [--expected-digest <sha256>]
|
|
38
|
+
Save an inert draft; review and activate it in the native app
|
|
33
39
|
ghostget imessage transport install --binary <absolute-reviewed-imsg-file> [--json]
|
|
34
40
|
Install only the current reviewed iMessage transport bytes
|
|
35
41
|
ghostget plugin list [--json] List trusted source and installed portable plugins
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Canonical immutable Ghostget package release identity. */
|
|
2
|
-
export const GHOSTGET_VERSION = "0.
|
|
2
|
+
export const GHOSTGET_VERSION = "0.18.0" as const;
|