feat: expose browser receiver pairing API
This commit is contained in:
parent
e2d07145d6
commit
2b3c6d0557
|
|
@ -55,6 +55,10 @@ export interface SyncNowResult {
|
|||
conflicts?: SyncConflict[];
|
||||
applyErrors?: string[];
|
||||
}
|
||||
export interface BrowserReceiverPairing {
|
||||
receiverUrl: string;
|
||||
receiverToken: string;
|
||||
}
|
||||
export interface VerstakPluginAPI {
|
||||
readonly pluginId: string;
|
||||
settings: {
|
||||
|
|
@ -128,6 +132,10 @@ export interface VerstakPluginAPI {
|
|||
resetKey(): Promise<void>;
|
||||
now(): Promise<SyncNowResult>;
|
||||
};
|
||||
browserReceiver: {
|
||||
pairing(): Promise<BrowserReceiverPairing>;
|
||||
rotateToken(): Promise<BrowserReceiverPairing>;
|
||||
};
|
||||
dispose?: () => void;
|
||||
}
|
||||
export declare function createPluginAPI(_pluginId: string): VerstakPluginAPI;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"plugin-api.js","sourceRoot":"","sources":["../src/plugin-api.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,8EAA8E;AAC9E,gDAAgD;AA2KhD,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;AACtF,CAAC"}
|
||||
{"version":3,"file":"plugin-api.js","sourceRoot":"","sources":["../src/plugin-api.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,8EAA8E;AAC9E,gDAAgD;AAqLhD,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;AACtF,CAAC"}
|
||||
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,KAAK,EAAwB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAQ3E,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,4BAA4B,CAAC;CAC9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAetF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CASnF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,SAAgB,EAAE,OAAO,GAAE,oBAAyB,GAAG,gBAAgB,CA2VlH;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAgCxF;AAGD,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,EAAE,EAAE,CAAC"}
|
||||
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,KAAK,EAAwB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAQ3E,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,4BAA4B,CAAC;CAC9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAetF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CASnF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,SAAgB,EAAE,OAAO,GAAE,oBAAyB,GAAG,gBAAgB,CAqWlH;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAgCxF;AAGD,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,EAAE,EAAE,CAAC"}
|
||||
|
|
@ -412,6 +412,16 @@ export function createMockPluginAPI(pluginId = 'test.plugin', options = {}) {
|
|||
resetKey: vi.fn(async () => { }),
|
||||
now: vi.fn(async () => ({ pushed: 0, pulled: 0, serverSequence: 0 })),
|
||||
},
|
||||
browserReceiver: {
|
||||
pairing: vi.fn(async () => ({
|
||||
receiverUrl: 'http://127.0.0.1:47731/api/browser-inbox/v1/captures',
|
||||
receiverToken: 'mock-browser-receiver-token',
|
||||
})),
|
||||
rotateToken: vi.fn(async () => ({
|
||||
receiverUrl: 'http://127.0.0.1:47731/api/browser-inbox/v1/captures',
|
||||
receiverToken: 'mock-browser-receiver-token-rotated',
|
||||
})),
|
||||
},
|
||||
dispose: vi.fn(),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -45,7 +45,7 @@ export interface CapabilityEntry {
|
|||
pluginId: string;
|
||||
status: 'stable' | 'draft' | 'deprecated';
|
||||
}
|
||||
export type Permission = 'vault.read' | 'vault.write' | 'vault.watch' | 'files.read' | 'files.write' | 'files.delete' | 'files.openExternal' | 'workbench.open' | 'storage.namespace' | 'storage.migrations' | 'events.publish' | 'events.subscribe' | 'ui.register' | 'commands.register' | 'network.local' | 'network.remote' | 'process.spawn' | 'secrets.read' | 'secrets.write' | 'sync.participate';
|
||||
export type Permission = 'vault.read' | 'vault.write' | 'vault.watch' | 'files.read' | 'files.write' | 'files.delete' | 'files.openExternal' | 'workbench.open' | 'storage.namespace' | 'storage.migrations' | 'events.publish' | 'events.subscribe' | 'ui.register' | 'commands.register' | 'network.local' | 'network.remote' | 'process.spawn' | 'secrets.read' | 'secrets.write' | 'sync.participate' | 'browser.receiver.manage';
|
||||
export interface PermissionEntry {
|
||||
name: Permission;
|
||||
description: string;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -100,7 +100,8 @@
|
|||
"process.spawn",
|
||||
"secrets.read",
|
||||
"secrets.write",
|
||||
"sync.participate"
|
||||
"sync.participate",
|
||||
"browser.receiver.manage"
|
||||
]
|
||||
},
|
||||
"minItems": 1
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
{ "name": "process.spawn", "description": "Spawn external processes", "dangerous": true },
|
||||
{ "name": "secrets.read", "description": "Read secrets from the secret store", "dangerous": true },
|
||||
{ "name": "secrets.write", "description": "Write secrets to the secret store", "dangerous": true },
|
||||
{ "name": "sync.participate", "description": "Participate in vault sync", "dangerous": true }
|
||||
{ "name": "sync.participate", "description": "Participate in vault sync", "dangerous": true },
|
||||
{ "name": "browser.receiver.manage", "description": "View and rotate the local browser receiver pairing token", "dangerous": true }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ describe('VerstakPluginAPI contract', () => {
|
|||
expect(typeof api.sync.configure).toBe('function');
|
||||
expect(typeof api.sync.resetKey).toBe('function');
|
||||
expect(typeof api.sync.now).toBe('function');
|
||||
expect(typeof api.browserReceiver.pairing).toBe('function');
|
||||
expect(typeof api.browserReceiver.rotateToken).toBe('function');
|
||||
});
|
||||
|
||||
test('manifest schema accepts files permissions used by platform-test', () => {
|
||||
|
|
@ -68,6 +70,14 @@ describe('VerstakPluginAPI contract', () => {
|
|||
expect(permissionEnum).toEqual(expect.arrayContaining(['secrets.read', 'secrets.write']));
|
||||
});
|
||||
|
||||
test('browser receiver token management is declared as a dangerous platform contract', () => {
|
||||
const permissions = ((permissionsSchema as any).permissions || []) as Array<{ name: string; dangerous: boolean }>;
|
||||
const permissionEnum = ((manifestSchema as any).properties.permissions.items.enum || []) as string[];
|
||||
|
||||
expect(permissions).toContainEqual(expect.objectContaining({ name: 'browser.receiver.manage', dangerous: true }));
|
||||
expect(permissionEnum).toContain('browser.receiver.manage');
|
||||
});
|
||||
|
||||
test('file.changed schema documents watcher refresh payload', () => {
|
||||
const fileChanged = (vaultEventsSchema as any).events.find((event: any) => event.name === 'file.changed');
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ export interface SyncNowResult {
|
|||
applyErrors?: string[];
|
||||
}
|
||||
|
||||
export interface BrowserReceiverPairing {
|
||||
receiverUrl: string;
|
||||
receiverToken: string;
|
||||
}
|
||||
|
||||
export interface VerstakPluginAPI {
|
||||
readonly pluginId: string;
|
||||
|
||||
|
|
@ -171,6 +176,11 @@ export interface VerstakPluginAPI {
|
|||
now(): Promise<SyncNowResult>;
|
||||
};
|
||||
|
||||
browserReceiver: {
|
||||
pairing(): Promise<BrowserReceiverPairing>;
|
||||
rotateToken(): Promise<BrowserReceiverPairing>;
|
||||
};
|
||||
|
||||
dispose?: () => void;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -395,6 +395,16 @@ export function createMockPluginAPI(pluginId = 'test.plugin', options: MockPlugi
|
|||
resetKey: vi.fn(async () => {}),
|
||||
now: vi.fn(async () => ({ pushed: 0, pulled: 0, serverSequence: 0 })),
|
||||
},
|
||||
browserReceiver: {
|
||||
pairing: vi.fn(async () => ({
|
||||
receiverUrl: 'http://127.0.0.1:47731/api/browser-inbox/v1/captures',
|
||||
receiverToken: 'mock-browser-receiver-token',
|
||||
})),
|
||||
rotateToken: vi.fn(async () => ({
|
||||
receiverUrl: 'http://127.0.0.1:47731/api/browser-inbox/v1/captures',
|
||||
receiverToken: 'mock-browser-receiver-token-rotated',
|
||||
})),
|
||||
},
|
||||
dispose: vi.fn(),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,8 @@ export type Permission =
|
|||
| 'process.spawn'
|
||||
| 'secrets.read'
|
||||
| 'secrets.write'
|
||||
| 'sync.participate';
|
||||
| 'sync.participate'
|
||||
| 'browser.receiver.manage';
|
||||
|
||||
export interface PermissionEntry {
|
||||
name: Permission;
|
||||
|
|
|
|||
Loading…
Reference in New Issue