mirror of
https://github.com/yaklang/yaklang-chrome-extension.git
synced 2026-09-26 21:21:53 +08:00
refactor(authorization): simplify cross-instance testing
CI / Test and build (push) Canceled after 0s
CI / Test and build (push) Canceled after 0s
This commit is contained in:
@@ -92,213 +92,6 @@ describe('Bridge v3 protocol', () => {
|
||||
})).toThrow();
|
||||
});
|
||||
|
||||
it('binds authorization context capture to a proof, slot and exact document target', () => {
|
||||
expect(parseCapabilityParams('browser.authorization.context.capture', {
|
||||
tabId: 12,
|
||||
frameId: 0,
|
||||
documentId: 'document-1',
|
||||
isolationProofId: 'proof-1',
|
||||
slotId: 'left',
|
||||
accountLabel: '低权限账号',
|
||||
})).toEqual({
|
||||
tabId: 12,
|
||||
frameId: 0,
|
||||
documentId: 'document-1',
|
||||
isolationProofId: 'proof-1',
|
||||
slotId: 'left',
|
||||
accountLabel: '低权限账号',
|
||||
});
|
||||
expect(parseCapabilityParams('browser.authorization.context.get', {
|
||||
id: 'auth-context-1',
|
||||
})).toEqual({ id: 'auth-context-1' });
|
||||
expect(parseCapabilityParams('browser.authorization.context.attest', {
|
||||
tabId: 12,
|
||||
frameId: 0,
|
||||
documentId: 'document-1',
|
||||
})).toEqual({
|
||||
tabId: 12,
|
||||
frameId: 0,
|
||||
documentId: 'document-1',
|
||||
});
|
||||
expect(parseCapabilityParams('browser.authorization.context.attestation.get', {
|
||||
id: 'attestation-1',
|
||||
})).toEqual({ id: 'attestation-1' });
|
||||
expect(parseCapabilityParams('browser.isolation.container.open', {
|
||||
url: 'https://example.test/login',
|
||||
name: '身份 B',
|
||||
})).toEqual({
|
||||
url: 'https://example.test/login',
|
||||
name: '身份 B',
|
||||
});
|
||||
expect(parseCapabilityParams('browser.isolation.container.list', {})).toEqual({});
|
||||
expect(parseCapabilityParams('browser.isolation.container.remove', {
|
||||
cookieStoreId: 'firefox-container-7',
|
||||
})).toEqual({ cookieStoreId: 'firefox-container-7' });
|
||||
expect(parseCapabilityParams('browser.authorization.baseline.capture', {
|
||||
tabId: 12,
|
||||
frameId: 0,
|
||||
documentId: 'document-1',
|
||||
authContextKind: 'handle',
|
||||
authContextId: 'auth-context-1',
|
||||
networkRequestId: 'network-request-1',
|
||||
comparisonKey: 'A'.repeat(43),
|
||||
})).toMatchObject({
|
||||
authContextKind: 'handle',
|
||||
authContextId: 'auth-context-1',
|
||||
networkRequestId: 'network-request-1',
|
||||
});
|
||||
expect(parseCapabilityParams('browser.authorization.baseline.get', {
|
||||
id: 'baseline-1',
|
||||
})).toEqual({ id: 'baseline-1' });
|
||||
expect(parseCapabilityParams('browser.authorization.baseline.logical.bind', {
|
||||
id: 'baseline-1',
|
||||
profileId: 'profile-left',
|
||||
comparisonKey: 'A'.repeat(43),
|
||||
})).toEqual({
|
||||
id: 'baseline-1',
|
||||
profileId: 'profile-left',
|
||||
comparisonKey: 'A'.repeat(43),
|
||||
});
|
||||
expect(parseCapabilityParams('browser.authorization.baseline.candidates', {
|
||||
tabId: 12,
|
||||
frameId: 0,
|
||||
authContextKind: 'attestation',
|
||||
authContextId: 'attestation-1',
|
||||
limit: 50,
|
||||
})).toMatchObject({
|
||||
authContextKind: 'attestation',
|
||||
authContextId: 'attestation-1',
|
||||
limit: 50,
|
||||
});
|
||||
expect(parseCapabilityParams('browser.authorization.baseline.resource.get', {
|
||||
id: 'baseline-1',
|
||||
selector: { source: 'wire', location: 'query', path: 'query.orderId' },
|
||||
})).toEqual({
|
||||
id: 'baseline-1',
|
||||
selector: { source: 'wire', location: 'query', path: 'query.orderId' },
|
||||
});
|
||||
expect(parseCapabilityParams('browser.authorization.baseline.compile', {
|
||||
id: 'baseline-1',
|
||||
selector: { source: 'wire', location: 'query', path: 'query.orderId' },
|
||||
replacement: {
|
||||
version: 1,
|
||||
baselineId: 'baseline-2',
|
||||
source: 'wire',
|
||||
location: 'query',
|
||||
path: 'query.orderId',
|
||||
valueType: 'string',
|
||||
byteLength: 2,
|
||||
valueBase64: 'NDI=',
|
||||
valueFingerprint: `workspace-hmac-sha256:${'a'.repeat(64)}`,
|
||||
},
|
||||
comparisonKey: 'A'.repeat(43),
|
||||
})).toMatchObject({
|
||||
id: 'baseline-1',
|
||||
replacement: { baselineId: 'baseline-2', valueBase64: 'NDI=' },
|
||||
});
|
||||
expect(parseCapabilityParams('browser.authorization.baseline.compile', {
|
||||
id: 'baseline-1',
|
||||
selector: {
|
||||
source: 'wire',
|
||||
location: 'body',
|
||||
path: 'body.variables.orderId',
|
||||
},
|
||||
replacement: {
|
||||
version: 1,
|
||||
baselineId: 'baseline-2',
|
||||
source: 'wire',
|
||||
location: 'body',
|
||||
path: 'body.variables.orderId',
|
||||
valueType: 'number',
|
||||
byteLength: 2,
|
||||
valueBase64: 'ODQ=',
|
||||
valueFingerprint: `workspace-hmac-sha256:${'b'.repeat(64)}`,
|
||||
},
|
||||
comparisonKey: 'A'.repeat(43),
|
||||
})).toMatchObject({
|
||||
replacement: { valueType: 'number', valueBase64: 'ODQ=' },
|
||||
});
|
||||
expect(parseCapabilityParams('browser.authorization.baseline.transform.inspect', {
|
||||
id: 'baseline-1',
|
||||
profileId: 'profile-left',
|
||||
})).toEqual({
|
||||
id: 'baseline-1',
|
||||
profileId: 'profile-left',
|
||||
});
|
||||
expect(parseCapabilityParams('browser.authorization.baseline.packet.compile', {
|
||||
id: 'baseline-1',
|
||||
})).toEqual({ id: 'baseline-1' });
|
||||
expect(parseCapabilityParams('browser.authorization.baseline.transform.compile', {
|
||||
id: 'baseline-1',
|
||||
selector: { source: 'wire', location: 'query', path: 'query.orderId' },
|
||||
replacement: {
|
||||
version: 1,
|
||||
baselineId: 'baseline-2',
|
||||
source: 'wire',
|
||||
location: 'query',
|
||||
path: 'query.orderId',
|
||||
valueType: 'string',
|
||||
byteLength: 2,
|
||||
valueBase64: 'NDI=',
|
||||
valueFingerprint: `workspace-hmac-sha256:${'a'.repeat(64)}`,
|
||||
},
|
||||
comparisonKey: 'A'.repeat(43),
|
||||
profileId: 'profile-left',
|
||||
bindingFingerprint: `sha256:${'b'.repeat(64)}`,
|
||||
})).toMatchObject({
|
||||
id: 'baseline-1',
|
||||
profileId: 'profile-left',
|
||||
bindingFingerprint: `sha256:${'b'.repeat(64)}`,
|
||||
});
|
||||
expect(() => parseCapabilityParams('browser.authorization.context.capture', {
|
||||
tabId: 12,
|
||||
isolationProofId: 'proof-1',
|
||||
slotId: 'middle',
|
||||
})).toThrow();
|
||||
expect(() => parseCapabilityParams('browser.isolation.container.remove', {
|
||||
cookieStoreId: 'firefox-default',
|
||||
})).toThrow();
|
||||
expect(() => parseCapabilityParams('browser.authorization.context.get', {
|
||||
id: '',
|
||||
})).toThrow();
|
||||
expect(() => parseCapabilityParams('browser.authorization.context.attestation.get', {
|
||||
id: '',
|
||||
})).toThrow();
|
||||
expect(() => parseCapabilityParams('browser.authorization.baseline.capture', {
|
||||
tabId: 12,
|
||||
authContextKind: 'handle',
|
||||
authContextId: 'auth-context-1',
|
||||
networkRequestId: 'network-request-1',
|
||||
comparisonKey: 'short',
|
||||
})).toThrow();
|
||||
expect(() => parseCapabilityParams('browser.authorization.baseline.candidates', {
|
||||
tabId: 12,
|
||||
authContextKind: 'handle',
|
||||
authContextId: 'auth-context-1',
|
||||
limit: 201,
|
||||
})).toThrow();
|
||||
expect(() => parseCapabilityParams('browser.authorization.baseline.resource.get', {
|
||||
id: 'baseline-1',
|
||||
selector: { location: 'body', path: 'body.orderId' },
|
||||
})).toThrow();
|
||||
expect(() => parseCapabilityParams('browser.authorization.baseline.compile', {
|
||||
id: 'baseline-1',
|
||||
selector: { source: 'wire', location: 'query', path: 'query.orderId' },
|
||||
replacement: {
|
||||
version: 1,
|
||||
baselineId: 'baseline-2',
|
||||
source: 'wire',
|
||||
location: 'query',
|
||||
path: 'query.orderId',
|
||||
valueType: 'string',
|
||||
byteLength: 2,
|
||||
valueBase64: 'not base64',
|
||||
valueFingerprint: `workspace-hmac-sha256:${'a'.repeat(64)}`,
|
||||
},
|
||||
comparisonKey: 'A'.repeat(43),
|
||||
})).toThrow();
|
||||
});
|
||||
|
||||
it('accepts automatic selected-frame capture and rejects the legacy expression contract', () => {
|
||||
expect(parseCapabilityParams('browser.callable.create', {
|
||||
source: 'deep-capture', strategy: 'selected-frame', callFrameId: 'frame-1', name: 'Envelope',
|
||||
|
||||
@@ -33,7 +33,6 @@ export interface BridgePairingEnvelope {
|
||||
}
|
||||
|
||||
const id = v.pipe(v.string(), v.trim(), v.minLength(1), v.maxLength(160));
|
||||
const comparisonKey = v.pipe(v.string(), v.regex(/^[A-Za-z0-9_-]{43}$/));
|
||||
const sha256Fingerprint = v.pipe(v.string(), v.regex(/^sha256:[a-f0-9]{64}$/));
|
||||
const tabId = v.pipe(v.number(), v.safeInteger(), v.minValue(1));
|
||||
const httpUrl = v.pipe(
|
||||
@@ -80,23 +79,6 @@ const deepCaptureMatcher = v.variant('kind', [
|
||||
const captureId = v.pipe(v.string(), v.trim(), v.minLength(1), v.maxLength(160));
|
||||
const nodeId = v.pipe(v.string(), v.trim(), v.minLength(1), v.maxLength(80));
|
||||
const valuePath = v.pipe(v.string(), v.trim(), v.minLength(1), v.maxLength(512));
|
||||
const authorizationSelector = v.strictObject({
|
||||
source: v.picklist(['wire', 'logical']),
|
||||
location: v.picklist(['header', 'path', 'query', 'body']),
|
||||
path: valuePath,
|
||||
});
|
||||
const authorizationResourceValue = v.strictObject({
|
||||
version: v.literal(1),
|
||||
baselineId: id,
|
||||
source: v.picklist(['wire', 'logical']),
|
||||
location: v.picklist(['header', 'path', 'query', 'body']),
|
||||
path: valuePath,
|
||||
valueType: v.picklist(['string', 'number', 'boolean']),
|
||||
byteLength: v.pipe(v.number(), v.safeInteger(), v.minValue(0), v.maxValue(8 * 1_024)),
|
||||
valueBase64: v.pipe(v.string(), v.maxLength(11_000), v.regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/)),
|
||||
valueFingerprint: v.pipe(v.string(), v.regex(/^workspace-hmac-sha256:[a-f0-9]{64}$/)),
|
||||
logicalBindingFingerprint: v.optional(sha256Fingerprint),
|
||||
});
|
||||
export const capabilityParams = {
|
||||
'system.ping': v.optional(v.strictObject({})),
|
||||
'browser.tabs': v.optional(v.strictObject({})),
|
||||
@@ -119,57 +101,6 @@ export const capabilityParams = {
|
||||
'browser.isolation.container.remove': v.strictObject({
|
||||
cookieStoreId: v.pipe(v.string(), v.regex(/^firefox-container-[0-9]+$/)),
|
||||
}),
|
||||
'browser.authorization.context.capture': v.strictObject({
|
||||
...targetFields,
|
||||
isolationProofId: id,
|
||||
slotId: v.picklist(['left', 'right']),
|
||||
accountLabel: v.optional(v.pipe(v.string(), v.trim(), v.maxLength(80))),
|
||||
}),
|
||||
'browser.authorization.context.get': v.strictObject({ id }),
|
||||
'browser.authorization.context.attest': v.strictObject(targetFields),
|
||||
'browser.authorization.context.attestation.get': v.strictObject({ id }),
|
||||
'browser.authorization.baseline.capture': v.strictObject({
|
||||
...targetFields,
|
||||
authContextKind: v.picklist(['handle', 'attestation']),
|
||||
authContextId: id,
|
||||
networkRequestId: id,
|
||||
comparisonKey,
|
||||
}),
|
||||
'browser.authorization.baseline.candidates': v.strictObject({
|
||||
...targetFields,
|
||||
authContextKind: v.picklist(['handle', 'attestation']),
|
||||
authContextId: id,
|
||||
limit: v.optional(v.pipe(v.number(), v.safeInteger(), v.minValue(1), v.maxValue(200))),
|
||||
}),
|
||||
'browser.authorization.baseline.get': v.strictObject({ id }),
|
||||
'browser.authorization.baseline.logical.bind': v.strictObject({
|
||||
id,
|
||||
profileId: id,
|
||||
comparisonKey,
|
||||
}),
|
||||
'browser.authorization.baseline.resource.get': v.strictObject({
|
||||
id,
|
||||
selector: authorizationSelector,
|
||||
}),
|
||||
'browser.authorization.baseline.compile': v.strictObject({
|
||||
id,
|
||||
selector: authorizationSelector,
|
||||
replacement: authorizationResourceValue,
|
||||
comparisonKey,
|
||||
}),
|
||||
'browser.authorization.baseline.packet.compile': v.strictObject({ id }),
|
||||
'browser.authorization.baseline.transform.inspect': v.strictObject({
|
||||
id,
|
||||
profileId: id,
|
||||
}),
|
||||
'browser.authorization.baseline.transform.compile': v.strictObject({
|
||||
id,
|
||||
selector: authorizationSelector,
|
||||
replacement: authorizationResourceValue,
|
||||
comparisonKey,
|
||||
profileId: id,
|
||||
bindingFingerprint: sha256Fingerprint,
|
||||
}),
|
||||
'browser.context': v.optional(v.strictObject({
|
||||
...targetFields,
|
||||
includeDom: v.optional(v.boolean()),
|
||||
|
||||
@@ -69,87 +69,6 @@ describe('versioned Bridge capability catalog', () => {
|
||||
access: 'dangerous',
|
||||
scopes: ['browser.isolation.manage'],
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.context.capture')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'sensitive-read',
|
||||
scopes: ['browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'document',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.context.get')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'sensitive-read',
|
||||
scopes: ['browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.context.attest')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'sensitive-read',
|
||||
scopes: ['browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'document',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.context.attestation.get')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'sensitive-read',
|
||||
scopes: ['browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.baseline.capture')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'sensitive-read',
|
||||
scopes: ['browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'document',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.baseline.get')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'sensitive-read',
|
||||
scopes: ['browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.baseline.logical.bind')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'dangerous',
|
||||
scopes: expect.arrayContaining(['browser.network.sensitive.read', 'browser.transform.execute']),
|
||||
targetMode: 'none',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.baseline.candidates')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'read',
|
||||
scopes: ['browser.network.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'document',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.baseline.resource.get')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'sensitive-read',
|
||||
scopes: ['browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.baseline.compile')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'dangerous',
|
||||
scopes: ['browser.network.replay', 'browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.baseline.packet.compile')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'dangerous',
|
||||
scopes: ['browser.network.replay', 'browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.baseline.transform.inspect')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'sensitive-read',
|
||||
scopes: expect.arrayContaining(['browser.transform.read']),
|
||||
targetMode: 'none',
|
||||
});
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.authorization.baseline.transform.compile')).toMatchObject({
|
||||
domain: 'authorization',
|
||||
access: 'dangerous',
|
||||
scopes: expect.arrayContaining(['browser.network.replay', 'browser.transform.execute']),
|
||||
targetMode: 'none',
|
||||
});
|
||||
expect(capabilityBaseScope('browser.authorization.baseline.compile')).toBe('browser.network.replay');
|
||||
expect(capabilityBaseScope('browser.authorization.baseline.packet.compile')).toBe('browser.network.replay');
|
||||
expect(capabilityBaseScope('browser.authorization.baseline.transform.compile')).toBe('browser.network.replay');
|
||||
expect(catalog.capabilities.find((capability) => capability.method === 'browser.isolation.container.open')).toBeUndefined();
|
||||
expect(capabilityBaseScope('missing.capability')).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -70,71 +70,6 @@ const CAPABILITY_METADATA = {
|
||||
domain: 'isolation', access: 'dangerous', summary: '关闭并删除由 Yakit 创建的临时 Firefox Container',
|
||||
scopes: ['browser.isolation.manage'], targetMode: 'none', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.context.capture': {
|
||||
domain: 'authorization', access: 'sensitive-read', summary: '为隔离身份生成不含原始凭据的短时认证上下文句柄',
|
||||
scopes: ['browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'document', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.context.get': {
|
||||
domain: 'authorization', access: 'sensitive-read', summary: '实时复核并读取当前浏览器实例中的短时认证上下文句柄',
|
||||
scopes: ['browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.context.attest': {
|
||||
domain: 'authorization', access: 'sensitive-read', summary: '为单个隔离页面生成不含原始凭据的跨设备认证证明',
|
||||
scopes: ['browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'document', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.context.attestation.get': {
|
||||
domain: 'authorization', access: 'sensitive-read', summary: '实时复核跨设备认证证明及其目标文档',
|
||||
scopes: ['browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.baseline.capture': {
|
||||
domain: 'authorization', access: 'sensitive-read', summary: '将已捕获请求封存为不暴露凭据值的短时授权基线',
|
||||
scopes: ['browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'document', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.baseline.candidates': {
|
||||
domain: 'authorization', access: 'read', summary: '列出不包含 Header 或 Body 值的授权基线请求候选',
|
||||
scopes: ['browser.network.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'document', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.baseline.get': {
|
||||
domain: 'authorization', access: 'sensitive-read', summary: '实时复核授权基线及其认证上下文',
|
||||
scopes: ['browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.baseline.logical.bind': {
|
||||
domain: 'authorization', access: 'dangerous', summary: '在本机验证明文网关生成结构,并将短时逻辑字段 HMAC 绑定到授权基线',
|
||||
scopes: ['browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read', 'browser.transform.execute'],
|
||||
targetMode: 'none', defaultTimeoutMs: REPLAY_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.baseline.resource.get': {
|
||||
domain: 'authorization', access: 'sensitive-read', summary: '读取已确认资源选择器的单个短时值,用于跨身份矩阵',
|
||||
scopes: ['browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.baseline.compile': {
|
||||
domain: 'authorization', access: 'dangerous', summary: '在实时复核身份后编译一次供 Yak 受限执行器使用的短时请求',
|
||||
scopes: ['browser.network.replay', 'browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none', defaultTimeoutMs: REPLAY_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.baseline.packet.compile': {
|
||||
domain: 'authorization', access: 'dangerous', summary: '在实时复核身份后编译不可变的完整操作模板或认证骨架',
|
||||
scopes: ['browser.network.replay', 'browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read'],
|
||||
targetMode: 'none', defaultTimeoutMs: REPLAY_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.baseline.transform.inspect': {
|
||||
domain: 'authorization', access: 'sensitive-read', summary: '验证身份页面的明文网关是否完整覆盖授权请求动态字段',
|
||||
scopes: ['browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read', 'browser.transform.read'],
|
||||
targetMode: 'none', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
},
|
||||
'browser.authorization.baseline.transform.compile': {
|
||||
domain: 'authorization', access: 'dangerous', summary: '在发起身份自己的页面环境重算签名、Nonce 与时间字段后编译请求',
|
||||
scopes: ['browser.network.replay', 'browser.network.sensitive.read', 'browser.isolation.read', 'browser.cookies.read', 'browser.storage.read', 'browser.transform.execute'],
|
||||
targetMode: 'none', defaultTimeoutMs: REPLAY_TIMEOUT_MS,
|
||||
},
|
||||
'browser.frames': {
|
||||
domain: 'page', access: 'read', summary: '列出浏览器实例指定标签页中的 Frame',
|
||||
scopes: ['browser.tabs.read'], targetMode: 'tab', defaultTimeoutMs: READ_TIMEOUT_MS,
|
||||
|
||||
@@ -82,11 +82,11 @@ describe('extension request schemas', () => {
|
||||
expect(parseExtensionRequest({
|
||||
action: 'authorization.engine.task',
|
||||
payload: {
|
||||
schema: 'authorization.workspace.create',
|
||||
schema: 'authorization.capture.start',
|
||||
payload: {
|
||||
mode: 'horizontal',
|
||||
left: { tabId: 12, frameId: 0, accountLabel: 'A' },
|
||||
right: { tabId: 13, frameId: 0, accountLabel: 'B' },
|
||||
left: { deviceId: 'browser-a', tabId: 12 },
|
||||
right: { deviceId: 'browser-b', tabId: 13 },
|
||||
side: 'left',
|
||||
},
|
||||
timeoutMs: 60_000,
|
||||
},
|
||||
|
||||
@@ -287,20 +287,12 @@ const payloadSchemas = {
|
||||
}),
|
||||
'authorization.engine.task': v.strictObject({
|
||||
schema: v.picklist([
|
||||
'authorization.workspace.create',
|
||||
'authorization.workspace.inspect',
|
||||
'authorization.capture.start',
|
||||
'authorization.capture.status',
|
||||
'authorization.capture.stop',
|
||||
'authorization.baseline.candidates',
|
||||
'authorization.baseline.bind',
|
||||
'authorization.logical.bind',
|
||||
'authorization.plan.create',
|
||||
'authorization.plan.execute',
|
||||
'authorization.evidence.inspect',
|
||||
'authorization.evidence.packet',
|
||||
'authorization.evidence.diff',
|
||||
'authorization.evidence.validate',
|
||||
'authorization.requests',
|
||||
'authorization.pair.inspect',
|
||||
'authorization.execute',
|
||||
]),
|
||||
payload: v.record(v.string(), v.unknown()),
|
||||
timeoutMs: v.optional(v.pipe(v.number(), v.safeInteger(), v.minValue(5_000), v.maxValue(120_000))),
|
||||
|
||||
Reference in New Issue
Block a user