@wenathlan/extension 1.1.43 → 1.1.44
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/README.md +5 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +684 -9
- package/dist/index.js.map +4 -4
- package/dist/memory.d.ts +35 -5
- package/dist/memory.d.ts.map +1 -1
- package/dist/netauth.d.ts +46 -0
- package/dist/netauth.d.ts.map +1 -0
- package/dist/netcontrol.d.ts +96 -0
- package/dist/netcontrol.d.ts.map +1 -0
- package/dist/policy.d.ts +16 -0
- package/dist/policy.d.ts.map +1 -1
- package/dist/protocol.d.ts +38 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/types.d.ts +158 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/extension/dist/background.js +1085 -24
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/manifest.json +1 -1
- package/extension/dist/pagebridge.js +24 -3
- package/extension/dist/pagebridge.js.map +2 -2
- package/extension/dist/popup.html +1 -1
- package/extension/dist/popup.js +11 -2
- package/extension/dist/popup.js.map +2 -2
- package/extension/dist/sidepanel.html +1 -1
- package/extension/dist/sidepanel.js +80 -2
- package/extension/dist/sidepanel.js.map +2 -2
- package/extension/dist/style.css +1 -0
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1648,15 +1648,22 @@ var sessionmemory = class {
|
|
|
1648
1648
|
async getfetchconsents() {
|
|
1649
1649
|
return await this.adapter.get("fetchconsents") ?? [];
|
|
1650
1650
|
}
|
|
1651
|
-
/** Stores one api key
|
|
1652
|
-
async setapikey(
|
|
1653
|
-
const records = (await this.adapter.get("apikeys") ?? []).filter((item) => item.name !==
|
|
1654
|
-
await this.adapter.set("apikeys", [
|
|
1651
|
+
/** Stores one api key entry with its origin scope and created time, replacing the previous entry of that name; the key material stays behind its storage id. */
|
|
1652
|
+
async setapikey(entry) {
|
|
1653
|
+
const records = (await this.adapter.get("apikeys") ?? []).filter((item) => item.name !== entry.name);
|
|
1654
|
+
await this.adapter.set("apikeys", [entry, ...records]);
|
|
1655
1655
|
}
|
|
1656
|
-
/** Returns every stored api key
|
|
1656
|
+
/** Returns every stored api key entry with its origin scope, header name, storage id and last use timestamp; key material never loads here. */
|
|
1657
1657
|
async getapikeys() {
|
|
1658
1658
|
return await this.adapter.get("apikeys") ?? [];
|
|
1659
1659
|
}
|
|
1660
|
+
/** Stamps the last use timestamp of one stored api key entry without ever loading the key material. */
|
|
1661
|
+
async touchapikey(name, at) {
|
|
1662
|
+
const records = await this.getapikeys();
|
|
1663
|
+
const entry = records.find((item) => item.name === name);
|
|
1664
|
+
if (!entry) return;
|
|
1665
|
+
await this.adapter.set("apikeys", [{ ...entry, lastuse: at }, ...records.filter((item) => item.name !== name)]);
|
|
1666
|
+
}
|
|
1660
1667
|
/** Removes one api key reference and its stored secret together. */
|
|
1661
1668
|
async removeapikey(name) {
|
|
1662
1669
|
const records = await this.getapikeys();
|
|
@@ -1753,6 +1760,74 @@ var sessionmemory = class {
|
|
|
1753
1760
|
async getsubscriptions() {
|
|
1754
1761
|
return await this.adapter.get("subscriptions") ?? [];
|
|
1755
1762
|
}
|
|
1763
|
+
/** Stores one registered request block rule of a run, replacing the previous rule of that id; every rule reverts and stays auditable after the run ends. */
|
|
1764
|
+
async addblockrule(rule) {
|
|
1765
|
+
const records = (await this.adapter.get("blockrules") ?? []).filter((item) => item.id !== rule.id);
|
|
1766
|
+
await this.adapter.set("blockrules", [rule, ...records]);
|
|
1767
|
+
}
|
|
1768
|
+
/** Returns every stored block rule, newest first. */
|
|
1769
|
+
async getblockrules() {
|
|
1770
|
+
return await this.adapter.get("blockrules") ?? [];
|
|
1771
|
+
}
|
|
1772
|
+
/** Stores one registered response mock fixture of a run, replacing the previous fixture of that id; the fixture body stays out of every audit trail. */
|
|
1773
|
+
async addmockspec(spec) {
|
|
1774
|
+
const records = (await this.adapter.get("mockspecs") ?? []).filter((item) => item.id !== spec.id);
|
|
1775
|
+
await this.adapter.set("mockspecs", [spec, ...records]);
|
|
1776
|
+
}
|
|
1777
|
+
/** Returns every stored mock fixture, newest first. */
|
|
1778
|
+
async getmockspecs() {
|
|
1779
|
+
return await this.adapter.get("mockspecs") ?? [];
|
|
1780
|
+
}
|
|
1781
|
+
/** Stores one registered header rewrite rule of a run, replacing the previous rule of that id; the provenance of every applied rule stays auditable. */
|
|
1782
|
+
async addheaderule(rule) {
|
|
1783
|
+
const records = (await this.adapter.get("headerules") ?? []).filter((item) => item.id !== rule.id);
|
|
1784
|
+
await this.adapter.set("headerules", [rule, ...records]);
|
|
1785
|
+
}
|
|
1786
|
+
/** Returns every stored header rewrite rule, newest first. */
|
|
1787
|
+
async getheaderules() {
|
|
1788
|
+
return await this.adapter.get("headerules") ?? [];
|
|
1789
|
+
}
|
|
1790
|
+
/** Stores one cookie operation of a run per domain with its timestamp; cookie values never enter the operation record. */
|
|
1791
|
+
async addcookieop(operation) {
|
|
1792
|
+
const records = await this.adapter.get("cookieops") ?? [];
|
|
1793
|
+
await this.adapter.set("cookieops", [operation, ...records]);
|
|
1794
|
+
}
|
|
1795
|
+
/** Returns every stored cookie operation, newest first, optionally filtered by domain. */
|
|
1796
|
+
async getcookieops(domain) {
|
|
1797
|
+
const records = await this.adapter.get("cookieops") ?? [];
|
|
1798
|
+
return records.filter((item) => domain === void 0 || item.domain === domain);
|
|
1799
|
+
}
|
|
1800
|
+
/** Stores one token record of a provider with scopes, origin scope and expiry; the token values stay behind their storage ids. */
|
|
1801
|
+
async addtoken(record2) {
|
|
1802
|
+
const records = (await this.adapter.get("tokens") ?? []).filter((item) => item.id !== record2.id);
|
|
1803
|
+
await this.adapter.set("tokens", [record2, ...records]);
|
|
1804
|
+
}
|
|
1805
|
+
/** Returns every stored token record, newest first, optionally filtered by provider; token values never load here. */
|
|
1806
|
+
async listtokens(provider) {
|
|
1807
|
+
const records = await this.adapter.get("tokens") ?? [];
|
|
1808
|
+
return records.filter((item) => provider === void 0 || item.provider === provider);
|
|
1809
|
+
}
|
|
1810
|
+
/** Stores one applied proxy route of a run with its apply time, replacing the previous route of that id; the history keeps the revert times. */
|
|
1811
|
+
async addproxyroute(route) {
|
|
1812
|
+
const records = (await this.adapter.get("proxyroutes") ?? []).filter((item) => item.id !== route.id);
|
|
1813
|
+
await this.adapter.set("proxyroutes", [route, ...records]);
|
|
1814
|
+
}
|
|
1815
|
+
/** Returns every stored proxy route with apply and revert times, newest first. */
|
|
1816
|
+
async getproxyroutes() {
|
|
1817
|
+
return await this.adapter.get("proxyroutes") ?? [];
|
|
1818
|
+
}
|
|
1819
|
+
/** Stores one parsed rate limit read per origin, replacing the previous read of that origin. */
|
|
1820
|
+
async setratelimit(read) {
|
|
1821
|
+
const records = (await this.adapter.get("ratelimits") ?? []).filter((item) => item.origin !== read.origin);
|
|
1822
|
+
await this.adapter.set("ratelimits", [read, ...records]);
|
|
1823
|
+
}
|
|
1824
|
+
/** Returns every stored rate limit read whose reset window has not passed yet; expired states drop out at their reset windows. */
|
|
1825
|
+
async getratelimits(now) {
|
|
1826
|
+
const records = await this.adapter.get("ratelimits") ?? [];
|
|
1827
|
+
const live = records.filter((item) => item.resetat > now);
|
|
1828
|
+
if (live.length !== records.length) await this.adapter.set("ratelimits", live);
|
|
1829
|
+
return live;
|
|
1830
|
+
}
|
|
1756
1831
|
};
|
|
1757
1832
|
function mediakindof(record2) {
|
|
1758
1833
|
if ("pages" in record2) return "pdf";
|
|
@@ -1796,6 +1871,315 @@ function randomid() {
|
|
|
1796
1871
|
return crypto.randomUUID();
|
|
1797
1872
|
}
|
|
1798
1873
|
|
|
1874
|
+
// netauth.ts
|
|
1875
|
+
function oauthflowof(value) {
|
|
1876
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1877
|
+
const options = value;
|
|
1878
|
+
if (typeof options.provider !== "string" || !options.provider.trim()) return void 0;
|
|
1879
|
+
if (typeof options.authorizeurl !== "string" || !options.authorizeurl.trim()) return void 0;
|
|
1880
|
+
if (typeof options.tokenurl !== "string" || !options.tokenurl.trim()) return void 0;
|
|
1881
|
+
if (!Array.isArray(options.scopes) || options.scopes.length === 0 || !options.scopes.every((item) => typeof item === "string" && item.trim().length > 0)) return void 0;
|
|
1882
|
+
if (typeof options.redirectorigin !== "string" || !options.redirectorigin.trim()) return void 0;
|
|
1883
|
+
return { provider: options.provider.trim(), authorizeurl: options.authorizeurl.trim(), tokenurl: options.tokenurl.trim(), scopes: options.scopes.map((item) => item.trim()), redirectorigin: options.redirectorigin.trim() };
|
|
1884
|
+
}
|
|
1885
|
+
function authorizeurl(flow, state) {
|
|
1886
|
+
const url = new URL(flow.authorizeurl);
|
|
1887
|
+
url.searchParams.set("response_type", "code");
|
|
1888
|
+
url.searchParams.set("redirect_uri", flow.redirectorigin);
|
|
1889
|
+
url.searchParams.set("scope", flow.scopes.join(" "));
|
|
1890
|
+
url.searchParams.set("state", state);
|
|
1891
|
+
return url.toString();
|
|
1892
|
+
}
|
|
1893
|
+
function capturecode(url, redirectorigin, state) {
|
|
1894
|
+
let parsed;
|
|
1895
|
+
try {
|
|
1896
|
+
parsed = new URL(url);
|
|
1897
|
+
} catch {
|
|
1898
|
+
return { error: "The redirect url does not parse for the code capture." };
|
|
1899
|
+
}
|
|
1900
|
+
const granted = redirectorigin.includes("/", redirectorigin.indexOf("://") + 3) ? `${parsed.origin}${parsed.pathname}`.startsWith(redirectorigin) : parsed.origin === redirectorigin;
|
|
1901
|
+
if (!granted) return { error: `The redirect landed on ${parsed.origin} outside the granted redirect origin ${redirectorigin}.` };
|
|
1902
|
+
const returned = parsed.searchParams.get("state");
|
|
1903
|
+
if (returned !== state) return { error: "The redirect state token does not match the reviewed flow." };
|
|
1904
|
+
const error = parsed.searchParams.get("error");
|
|
1905
|
+
if (error) return { error: `The provider refused the flow: ${error}.` };
|
|
1906
|
+
const code = parsed.searchParams.get("code");
|
|
1907
|
+
if (!code) return { error: "The redirect carries no authorization code." };
|
|
1908
|
+
return { code };
|
|
1909
|
+
}
|
|
1910
|
+
function parsetokens(body) {
|
|
1911
|
+
let parsed;
|
|
1912
|
+
try {
|
|
1913
|
+
parsed = JSON.parse(body);
|
|
1914
|
+
} catch {
|
|
1915
|
+
return void 0;
|
|
1916
|
+
}
|
|
1917
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
1918
|
+
const record2 = parsed;
|
|
1919
|
+
const tokens = {};
|
|
1920
|
+
if (typeof record2.access_token === "string" && record2.access_token) tokens.accesstoken = record2.access_token;
|
|
1921
|
+
if (typeof record2.refresh_token === "string" && record2.refresh_token) tokens.refreshtoken = record2.refresh_token;
|
|
1922
|
+
if (typeof record2.expires_in === "number" && Number.isFinite(record2.expires_in) && record2.expires_in >= 0) tokens.expiresin = record2.expires_in;
|
|
1923
|
+
if (typeof record2.scope === "string" && record2.scope.trim()) tokens.scopes = record2.scope.trim().split(/\s+/);
|
|
1924
|
+
if (tokens.accesstoken === void 0 && tokens.refreshtoken === void 0) return void 0;
|
|
1925
|
+
return tokens;
|
|
1926
|
+
}
|
|
1927
|
+
function tokenrequest(flow, input) {
|
|
1928
|
+
if (input.refreshtoken !== void 0) return { url: flow.tokenurl, body: urlencodeform([{ name: "grant_type", value: "refresh_token" }, { name: "refresh_token", value: input.refreshtoken }]) };
|
|
1929
|
+
return { url: flow.tokenurl, body: urlencodeform([{ name: "grant_type", value: "authorization_code" }, { name: "code", value: input.code ?? "" }, { name: "redirect_uri", value: flow.redirectorigin }]) };
|
|
1930
|
+
}
|
|
1931
|
+
function revocationruleof(value) {
|
|
1932
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1933
|
+
const options = value;
|
|
1934
|
+
if (!Array.isArray(options.tokenids) || options.tokenids.length === 0 || !options.tokenids.every((item) => typeof item === "string" && item.trim().length > 0)) return void 0;
|
|
1935
|
+
if (typeof options.reason !== "string" || !options.reason.trim()) return void 0;
|
|
1936
|
+
return { tokenids: options.tokenids.map((item) => item.trim()), reason: options.reason.trim(), revokedat: Date.now() };
|
|
1937
|
+
}
|
|
1938
|
+
function formpayloadof(value) {
|
|
1939
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1940
|
+
const options = value;
|
|
1941
|
+
if (typeof options.url !== "string" || !options.url.trim()) return void 0;
|
|
1942
|
+
if (!Array.isArray(options.fields) || options.fields.length === 0) return void 0;
|
|
1943
|
+
const fields = [];
|
|
1944
|
+
for (const item of options.fields) {
|
|
1945
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return void 0;
|
|
1946
|
+
const field = item;
|
|
1947
|
+
if (typeof field.name !== "string" || !field.name.trim()) return void 0;
|
|
1948
|
+
if (typeof field.value !== "string") return void 0;
|
|
1949
|
+
fields.push({ name: field.name.trim(), value: field.value });
|
|
1950
|
+
}
|
|
1951
|
+
return { url: options.url.trim(), fields };
|
|
1952
|
+
}
|
|
1953
|
+
function urlencodeform(fields) {
|
|
1954
|
+
return fields.map((field) => `${formencode(field.name)}=${formencode(field.value)}`).join("&");
|
|
1955
|
+
}
|
|
1956
|
+
function formencode(value) {
|
|
1957
|
+
const bytes = [...new TextEncoder().encode(value)];
|
|
1958
|
+
return bytes.map((byte) => byte >= 65 && byte <= 90 || byte >= 97 && byte <= 122 || byte >= 48 && byte <= 57 || byte === 45 || byte === 95 || byte === 46 || byte === 126 ? String.fromCharCode(byte) : `%${byte.toString(16).toUpperCase().padStart(2, "0")}`).join("");
|
|
1959
|
+
}
|
|
1960
|
+
function multipartpayloadof(value) {
|
|
1961
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1962
|
+
const options = value;
|
|
1963
|
+
if (typeof options.url !== "string" || !options.url.trim()) return void 0;
|
|
1964
|
+
if (!Array.isArray(options.files) || options.files.length === 0) return void 0;
|
|
1965
|
+
const fields = [];
|
|
1966
|
+
for (const item of Array.isArray(options.fields) ? options.fields : []) {
|
|
1967
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return void 0;
|
|
1968
|
+
const field = item;
|
|
1969
|
+
if (typeof field.name !== "string" || !field.name.trim()) return void 0;
|
|
1970
|
+
if (typeof field.value !== "string") return void 0;
|
|
1971
|
+
fields.push({ name: field.name.trim(), value: field.value });
|
|
1972
|
+
}
|
|
1973
|
+
const files = [];
|
|
1974
|
+
for (const item of options.files) {
|
|
1975
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return void 0;
|
|
1976
|
+
const file = item;
|
|
1977
|
+
if (typeof file.name !== "string" || !file.name.trim()) return void 0;
|
|
1978
|
+
if (typeof file.filename !== "string" || !file.filename.trim()) return void 0;
|
|
1979
|
+
if (typeof file.mime !== "string" || !file.mime.trim()) return void 0;
|
|
1980
|
+
if (typeof file.content !== "string") return void 0;
|
|
1981
|
+
if (file.reviewed !== true) return void 0;
|
|
1982
|
+
files.push({ name: file.name.trim(), filename: file.filename.trim(), mime: file.mime.trim(), content: file.content, reviewed: true });
|
|
1983
|
+
}
|
|
1984
|
+
const payload = { url: options.url.trim(), fields, files, ...typeof options.boundary === "string" && options.boundary.trim() ? { boundary: options.boundary.trim() } : {} };
|
|
1985
|
+
return payload;
|
|
1986
|
+
}
|
|
1987
|
+
function newboundary() {
|
|
1988
|
+
return `----devthink${Math.random().toString(16).slice(2)}${Date.now().toString(16)}`;
|
|
1989
|
+
}
|
|
1990
|
+
function multipartchunks(payload) {
|
|
1991
|
+
const boundary = payload.boundary ?? newboundary();
|
|
1992
|
+
const chunks = [];
|
|
1993
|
+
for (const field of payload.fields) chunks.push(`--${boundary}\r
|
|
1994
|
+
content-disposition: form-data; name="${field.name}"\r
|
|
1995
|
+
\r
|
|
1996
|
+
${field.value}\r
|
|
1997
|
+
`);
|
|
1998
|
+
for (const file of payload.files) chunks.push(`--${boundary}\r
|
|
1999
|
+
content-disposition: form-data; name="${file.name}"; filename="${file.filename}"\r
|
|
2000
|
+
content-type: ${file.mime}\r
|
|
2001
|
+
\r
|
|
2002
|
+
${file.content}\r
|
|
2003
|
+
`);
|
|
2004
|
+
chunks.push(`--${boundary}--\r
|
|
2005
|
+
`);
|
|
2006
|
+
return { chunks, boundary, bytes: chunks.reduce((total, chunk) => total + chunk.length, 0) };
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
// netcontrol.ts
|
|
2010
|
+
var controlkinds = ["blockrequest", "mockresponse", "rewriteheaders", "setcookies", "readcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles"];
|
|
2011
|
+
function patternorigin(pattern) {
|
|
2012
|
+
const trimmed = pattern.trim();
|
|
2013
|
+
if (!trimmed.startsWith("https://")) return void 0;
|
|
2014
|
+
const rest = trimmed.slice("https://".length);
|
|
2015
|
+
const host = rest.split("/")[0] ?? "";
|
|
2016
|
+
if (!host.trim()) return void 0;
|
|
2017
|
+
return `https://${host.toLowerCase()}`;
|
|
2018
|
+
}
|
|
2019
|
+
function matchurlpattern(pattern, url) {
|
|
2020
|
+
const origin = patternorigin(pattern);
|
|
2021
|
+
if (!origin) return false;
|
|
2022
|
+
let parsed;
|
|
2023
|
+
try {
|
|
2024
|
+
parsed = new URL(url);
|
|
2025
|
+
} catch {
|
|
2026
|
+
return false;
|
|
2027
|
+
}
|
|
2028
|
+
if (parsed.origin !== origin) return false;
|
|
2029
|
+
const patternpath = pattern.trim().slice(origin.length);
|
|
2030
|
+
if (patternpath === "" || patternpath === "/") return true;
|
|
2031
|
+
const segments = patternpath.split("/").filter((segment) => segment !== "");
|
|
2032
|
+
if (segments.includes("**")) return true;
|
|
2033
|
+
const pathsegments = parsed.pathname.split("/").filter((segment) => segment !== "");
|
|
2034
|
+
if (segments.length !== pathsegments.length) return false;
|
|
2035
|
+
return segments.every((segment, index) => segment === pathsegments[index] || segment.includes("*") && new RegExp(`^${segment.split("*").map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join(".*")}$`).test(pathsegments[index] ?? ""));
|
|
2036
|
+
}
|
|
2037
|
+
function blockruleof(value) {
|
|
2038
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
2039
|
+
const options = value;
|
|
2040
|
+
if (typeof options.urlpattern !== "string" || !options.urlpattern.trim()) return void 0;
|
|
2041
|
+
const rule = { urlpattern: options.urlpattern.trim() };
|
|
2042
|
+
if (Array.isArray(options.resourcetypes)) {
|
|
2043
|
+
const types = options.resourcetypes.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
2044
|
+
if (types.length === 0) return void 0;
|
|
2045
|
+
rule.resourcetypes = types;
|
|
2046
|
+
}
|
|
2047
|
+
return rule;
|
|
2048
|
+
}
|
|
2049
|
+
function newblockrule(input) {
|
|
2050
|
+
return { id: input.id, runid: input.runid, stepid: input.stepid, urlpattern: input.urlpattern, ...input.resourcetypes !== void 0 ? { resourcetypes: input.resourcetypes } : {}, hits: 0, registeredat: input.at };
|
|
2051
|
+
}
|
|
2052
|
+
function mockspecof(value) {
|
|
2053
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
2054
|
+
const options = value;
|
|
2055
|
+
if (typeof options.urlpattern !== "string" || !options.urlpattern.trim()) return void 0;
|
|
2056
|
+
if (typeof options.status !== "number" || !Number.isInteger(options.status) || options.status < 100 || options.status > 599) return void 0;
|
|
2057
|
+
const hasbody = typeof options.body === "string";
|
|
2058
|
+
const bodyref = typeof options.bodyref === "string" ? options.bodyref.trim() : "";
|
|
2059
|
+
if (!hasbody && bodyref === "") return void 0;
|
|
2060
|
+
const spec = { urlpattern: options.urlpattern.trim(), status: options.status };
|
|
2061
|
+
if (hasbody) spec.body = options.body;
|
|
2062
|
+
if (bodyref !== "") spec.bodyref = bodyref;
|
|
2063
|
+
if (options.headers && typeof options.headers === "object" && !Array.isArray(options.headers)) spec.headers = options.headers;
|
|
2064
|
+
if (options.reviewed === true) spec.reviewed = true;
|
|
2065
|
+
return spec;
|
|
2066
|
+
}
|
|
2067
|
+
function newmockspec(input) {
|
|
2068
|
+
return { id: input.id, runid: input.runid, stepid: input.stepid, urlpattern: input.urlpattern, status: input.status, ...input.headers !== void 0 ? { headers: input.headers } : {}, ...input.body !== void 0 ? { body: input.body } : {}, ...input.bodyref !== void 0 ? { bodyref: input.bodyref } : {}, reviewed: input.reviewed, hits: 0, registeredat: input.at };
|
|
2069
|
+
}
|
|
2070
|
+
function mockfor(url, specs) {
|
|
2071
|
+
return specs.find((spec) => spec.revertedat === void 0 && matchurlpattern(spec.urlpattern, url));
|
|
2072
|
+
}
|
|
2073
|
+
function headeruleof(value) {
|
|
2074
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
2075
|
+
const options = value;
|
|
2076
|
+
if (typeof options.urlpattern !== "string" || !options.urlpattern.trim()) return void 0;
|
|
2077
|
+
if (typeof options.name !== "string" || !options.name.trim()) return void 0;
|
|
2078
|
+
if (options.operation !== "set" && options.operation !== "append" && options.operation !== "remove") return void 0;
|
|
2079
|
+
if (options.operation === "remove" && options.value !== void 0) return void 0;
|
|
2080
|
+
if (options.operation !== "remove" && typeof options.value !== "string") return void 0;
|
|
2081
|
+
const rule = { urlpattern: options.urlpattern.trim(), name: options.name.trim(), operation: options.operation };
|
|
2082
|
+
if (options.operation !== "remove") rule.value = typeof options.value === "string" ? options.value : "";
|
|
2083
|
+
return rule;
|
|
2084
|
+
}
|
|
2085
|
+
function newheaderule(input) {
|
|
2086
|
+
return { id: input.id, runid: input.runid, stepid: input.stepid, urlpattern: input.urlpattern, name: input.name, operation: input.operation, ...input.value !== void 0 ? { value: input.value } : {}, hits: 0, registeredat: input.at };
|
|
2087
|
+
}
|
|
2088
|
+
function applyheaderules(url, headers, rules) {
|
|
2089
|
+
const rewritten = { ...headers };
|
|
2090
|
+
const applied = [];
|
|
2091
|
+
for (const rule of rules) {
|
|
2092
|
+
if (rule.revertedat !== void 0) continue;
|
|
2093
|
+
if (!matchurlpattern(rule.urlpattern, url)) continue;
|
|
2094
|
+
const name = rule.name;
|
|
2095
|
+
if (rule.operation === "remove") {
|
|
2096
|
+
delete rewritten[name];
|
|
2097
|
+
applied.push(rule);
|
|
2098
|
+
continue;
|
|
2099
|
+
}
|
|
2100
|
+
const value = rule.value ?? "";
|
|
2101
|
+
if (rule.operation === "set") rewritten[name] = value;
|
|
2102
|
+
else rewritten[name] = rewritten[name] !== void 0 ? `${rewritten[name]}, ${value}` : value;
|
|
2103
|
+
applied.push(rule);
|
|
2104
|
+
}
|
|
2105
|
+
return { headers: rewritten, applied };
|
|
2106
|
+
}
|
|
2107
|
+
function revertrule(rule, at) {
|
|
2108
|
+
if (rule.revertedat !== void 0) return rule;
|
|
2109
|
+
return { ...rule, revertedat: at };
|
|
2110
|
+
}
|
|
2111
|
+
function cookierecordof(value) {
|
|
2112
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
2113
|
+
const options = value;
|
|
2114
|
+
if (typeof options.name !== "string" || !options.name.trim()) return void 0;
|
|
2115
|
+
if (typeof options.domain !== "string" || !options.domain.trim()) return void 0;
|
|
2116
|
+
if (typeof options.path !== "string" || !options.path.trim()) return void 0;
|
|
2117
|
+
if (typeof options.value !== "string") return void 0;
|
|
2118
|
+
const record2 = { name: options.name.trim(), domain: options.domain.trim().toLowerCase(), path: options.path.trim(), value: options.value };
|
|
2119
|
+
if (typeof options.expiresat === "number" && Number.isFinite(options.expiresat)) record2.expiresat = options.expiresat;
|
|
2120
|
+
return record2;
|
|
2121
|
+
}
|
|
2122
|
+
function cookiedomaingranted(domain, grants) {
|
|
2123
|
+
const host = domain.trim().toLowerCase().replace(/^\./, "");
|
|
2124
|
+
return grants.some((grant) => {
|
|
2125
|
+
let granthost = "";
|
|
2126
|
+
try {
|
|
2127
|
+
granthost = new URL(grant).hostname.toLowerCase();
|
|
2128
|
+
} catch {
|
|
2129
|
+
return false;
|
|
2130
|
+
}
|
|
2131
|
+
return host === granthost || host.endsWith(`.${granthost}`);
|
|
2132
|
+
});
|
|
2133
|
+
}
|
|
2134
|
+
function redactedcookies(records) {
|
|
2135
|
+
return records.map((record2) => ({ name: record2.name, domain: record2.domain, path: record2.path, ...record2.expiresat !== void 0 ? { expiresat: record2.expiresat } : {} }));
|
|
2136
|
+
}
|
|
2137
|
+
function proxyrouteof(value) {
|
|
2138
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
2139
|
+
const options = value;
|
|
2140
|
+
if (options.scheme !== "http" && options.scheme !== "https" && options.scheme !== "socks4" && options.scheme !== "socks5") return void 0;
|
|
2141
|
+
if (typeof options.host !== "string" || !options.host.trim()) return void 0;
|
|
2142
|
+
if (typeof options.port !== "number" || !Number.isInteger(options.port) || options.port < 1 || options.port > 65535) return void 0;
|
|
2143
|
+
if (!Array.isArray(options.bypass) || options.bypass.length === 0 || !options.bypass.every((item) => typeof item === "string" && item.trim().length > 0)) return void 0;
|
|
2144
|
+
return { scheme: options.scheme, host: options.host.trim(), port: options.port, bypass: options.bypass.map((item) => item.trim()) };
|
|
2145
|
+
}
|
|
2146
|
+
function ratelimitreadof(headers, origin, now) {
|
|
2147
|
+
const pick = (name) => {
|
|
2148
|
+
for (const key of Object.keys(headers)) {
|
|
2149
|
+
if (key.toLowerCase() !== name) continue;
|
|
2150
|
+
const value = Number(headers[key]);
|
|
2151
|
+
return Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
2152
|
+
}
|
|
2153
|
+
return void 0;
|
|
2154
|
+
};
|
|
2155
|
+
const remaining = pick("x-ratelimit-remaining");
|
|
2156
|
+
const limit = pick("x-ratelimit-limit");
|
|
2157
|
+
const reset = pick("x-ratelimit-reset");
|
|
2158
|
+
if (remaining === void 0 && limit === void 0 && reset === void 0) return void 0;
|
|
2159
|
+
const read = { origin, ...remaining !== void 0 ? { remaining } : {}, ...limit !== void 0 ? { limit } : {}, resetat: now, at: now };
|
|
2160
|
+
if (reset !== void 0) read.resetat = reset > Math.floor(now / 1e3) ? reset * 1e3 : now + reset * 1e3;
|
|
2161
|
+
return read;
|
|
2162
|
+
}
|
|
2163
|
+
function retryafterof(status, headers) {
|
|
2164
|
+
if (status !== 429 && status !== 503) return void 0;
|
|
2165
|
+
for (const key of Object.keys(headers)) {
|
|
2166
|
+
if (key.toLowerCase() !== "retry-after") continue;
|
|
2167
|
+
const raw = headers[key];
|
|
2168
|
+
if (raw === void 0) continue;
|
|
2169
|
+
const value = raw.trim();
|
|
2170
|
+
const seconds = Number(value);
|
|
2171
|
+
if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
|
|
2172
|
+
const date = Date.parse(value);
|
|
2173
|
+
if (Number.isFinite(date)) return Math.max(0, date - Date.now());
|
|
2174
|
+
return void 0;
|
|
2175
|
+
}
|
|
2176
|
+
return void 0;
|
|
2177
|
+
}
|
|
2178
|
+
function ratelimitwait(state, now) {
|
|
2179
|
+
if (!state) return 0;
|
|
2180
|
+
return Math.max(0, state.resetat - now);
|
|
2181
|
+
}
|
|
2182
|
+
|
|
1799
2183
|
// netwatch.ts
|
|
1800
2184
|
var netwatchkinds = ["watchrequests", "readheaders", "capturebodies", "mapapi", "extractapi"];
|
|
1801
2185
|
function resourcefacts(entries) {
|
|
@@ -2201,9 +2585,9 @@ function polldecision(input) {
|
|
|
2201
2585
|
}
|
|
2202
2586
|
|
|
2203
2587
|
// policy.ts
|
|
2204
|
-
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage"]);
|
|
2588
|
+
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles"]);
|
|
2205
2589
|
var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction", "capturebodies"]);
|
|
2206
|
-
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures", "shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet", "capturepdf", "captureframe", "readmedia", "readassets", "probestream", "timelapse", "shotcanvas", "convertimage", "makethumbs", "fetchurl", "parsejson", "parsehtml", "opensocket", "waitmessage", "watchrequests", "readheaders", "mapapi", "subscribesse", "longpoll", "extractapi"]);
|
|
2590
|
+
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures", "shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet", "capturepdf", "captureframe", "readmedia", "readassets", "probestream", "timelapse", "shotcanvas", "convertimage", "makethumbs", "fetchurl", "parsejson", "parsehtml", "opensocket", "waitmessage", "watchrequests", "readheaders", "mapapi", "subscribesse", "longpoll", "extractapi", "readcookies"]);
|
|
2207
2591
|
var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
|
|
2208
2592
|
var watchactions = /* @__PURE__ */ new Set(["watchmutate", "watchbanner", "watchfocus", "watchtab"]);
|
|
2209
2593
|
var targetactions = /* @__PURE__ */ new Set(["inspect", "focus", "click", "type", "scroll", "select", "hover", "clickdeep", "rightclick", "doubleclick", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "highlight", "setattribute", "removeattribute", "waitfor", "shiftclick", "typetime", "appendtext", "setvalue", "typeedit", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "expanddetails", "verifyvisible", "verifyenabled", "pierceshadow", "deriveselector", "fingerprintsection", "submitform", "retryform", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcode", "consentpassword", "scrapetable", "paginateextract", "shotelement", "captureframe", "shotcanvas"]);
|
|
@@ -2218,6 +2602,7 @@ var mediaactions = /* @__PURE__ */ new Set(["capturepdf", "recordscreen", "captu
|
|
|
2218
2602
|
var httpactions = /* @__PURE__ */ new Set(["fetchurl", "parsejson", "parsehtml", "callrest", "callgraphql"]);
|
|
2219
2603
|
var socketactions = /* @__PURE__ */ new Set(["opensocket", "sendmessage", "waitmessage", "subscribesse", "longpoll"]);
|
|
2220
2604
|
var netwatchactions = /* @__PURE__ */ new Set(["watchrequests", "readheaders", "capturebodies", "mapapi", "extractapi"]);
|
|
2605
|
+
var controlactions = /* @__PURE__ */ new Set(["blockrequest", "mockresponse", "rewriteheaders", "setcookies", "readcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles"]);
|
|
2221
2606
|
var credentialheaders = /* @__PURE__ */ new Set(["authorization", "proxy-authorization", "cookie", "cookie2", "set-cookie", "api-key", "x-api-key", "x-auth-token", "x-session-token", "proxy-authorization"]);
|
|
2222
2607
|
var fieldkinds = ["text", "email", "phone", "date", "number", "select", "check", "radio", "file", "password", "card", "code"];
|
|
2223
2608
|
var layoutmutationactions = /* @__PURE__ */ new Set(["grouptabs", "colorgroup", "collapsegroup", "savelayout", "restorelayout"]);
|
|
@@ -2932,6 +3317,9 @@ function issocketkind(kind) {
|
|
|
2932
3317
|
function isnetwatchkind(kind) {
|
|
2933
3318
|
return netwatchactions.has(kind);
|
|
2934
3319
|
}
|
|
3320
|
+
function iscontrolkind(kind) {
|
|
3321
|
+
return controlactions.has(kind);
|
|
3322
|
+
}
|
|
2935
3323
|
function resolvedrisk(step) {
|
|
2936
3324
|
if (step.kind === "capturebodies") {
|
|
2937
3325
|
let options = {};
|
|
@@ -3230,6 +3618,163 @@ function validatenetwatchgrammar(step, options) {
|
|
|
3230
3618
|
}
|
|
3231
3619
|
return { allowed: true };
|
|
3232
3620
|
}
|
|
3621
|
+
function validatecontrolgrammar(step, options) {
|
|
3622
|
+
const kind = step.kind;
|
|
3623
|
+
if (kind === "blockrequest") {
|
|
3624
|
+
const rule = blockruleof(options.block);
|
|
3625
|
+
if (!rule) return { allowed: false, reason: "A reviewed block rule with a url pattern is required in options.block." };
|
|
3626
|
+
if (patternorigin(rule.urlpattern) === void 0) return { allowed: false, reason: "Block rules need an https origin pattern; patterns without a named origin are refused." };
|
|
3627
|
+
if (options.block.reviewed !== true) return { allowed: false, reason: "The block rule carries the explicit reviewed flag before any request is blocked." };
|
|
3628
|
+
}
|
|
3629
|
+
if (kind === "mockresponse") {
|
|
3630
|
+
const spec = mockspecof(options.mock);
|
|
3631
|
+
if (!spec) return { allowed: false, reason: "A reviewed mock fixture with a url pattern, status and its reviewed body or a captured body ref is required in options.mock." };
|
|
3632
|
+
if (patternorigin(spec.urlpattern) === void 0) return { allowed: false, reason: "Mock fixtures need an https origin pattern; patterns without a named origin are refused." };
|
|
3633
|
+
if (spec.reviewed !== true) return { allowed: false, reason: "Every mock fixture is reviewed with its full body or the referenced captured body through the explicit reviewed flag before it serves." };
|
|
3634
|
+
}
|
|
3635
|
+
if (kind === "rewriteheaders") {
|
|
3636
|
+
const rules = options.rules;
|
|
3637
|
+
if (!Array.isArray(rules) || rules.length === 0) return { allowed: false, reason: "A reviewed non-empty list of header rewrite rules is required in options.rules." };
|
|
3638
|
+
for (const item of rules) {
|
|
3639
|
+
const rule = headeruleof(item);
|
|
3640
|
+
if (!rule) return { allowed: false, reason: "Every header rewrite rule needs a url pattern, header name, a set, append or remove operation and its value." };
|
|
3641
|
+
if (patternorigin(rule.urlpattern) === void 0) return { allowed: false, reason: "Header rewrite rules must name their origin pattern explicitly; patterns without a named origin are refused." };
|
|
3642
|
+
}
|
|
3643
|
+
}
|
|
3644
|
+
if (kind === "setcookies") {
|
|
3645
|
+
const cookies = options.cookies;
|
|
3646
|
+
if (!Array.isArray(cookies) || cookies.length === 0) return { allowed: false, reason: "A reviewed non-empty list of cookie records is required in options.cookies." };
|
|
3647
|
+
for (const item of cookies) {
|
|
3648
|
+
if (!cookierecordof(item)) return { allowed: false, reason: "Every cookie record needs a name, domain, path and reviewed string value with an optional expiry." };
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
if (kind === "readcookies" && options.domain !== void 0 && !isnonempty(options.domain)) return { allowed: false, reason: "The reviewed cookie read domain must be a non-empty host." };
|
|
3652
|
+
if (kind === "clearcookies") {
|
|
3653
|
+
if (!isnonempty(options.domain)) return { allowed: false, reason: "A reviewed cookie domain is required before cookies are cleared." };
|
|
3654
|
+
if (options.names !== void 0 && (!Array.isArray(options.names) || options.names.length === 0 || !options.names.every((name) => isnonempty(name)))) return { allowed: false, reason: "The reviewed cookie clear list must be a non-empty list of cookie names when present." };
|
|
3655
|
+
}
|
|
3656
|
+
if (kind === "authflow") {
|
|
3657
|
+
const flow = oauthflowof(options.oauth);
|
|
3658
|
+
if (!flow) return { allowed: false, reason: "A reviewed oauth flow with provider, authorize url, token url, scopes and redirect origin is required in options.oauth." };
|
|
3659
|
+
if (!ishttpsurl(flow.authorizeurl) || !ishttpsurl(flow.tokenurl)) return { allowed: false, reason: "The oauth authorize and token urls must use HTTPS." };
|
|
3660
|
+
if (!ishttpsurl(flow.redirectorigin) && !/^https:\/\/[^/]+\/?$/.test(flow.redirectorigin)) return { allowed: false, reason: "The oauth redirect origin must be an HTTPS origin inside the grants." };
|
|
3661
|
+
const consent = authconsentgranted(step);
|
|
3662
|
+
if (!consent.allowed) return consent;
|
|
3663
|
+
}
|
|
3664
|
+
if (kind === "saveapikey") {
|
|
3665
|
+
const key = options.key;
|
|
3666
|
+
if (!key || typeof key !== "object" || Array.isArray(key)) return { allowed: false, reason: "A reviewed api key entry with name, origin scopes and header is required in options.key." };
|
|
3667
|
+
const entry = key;
|
|
3668
|
+
if (!isnonempty(entry.name)) return { allowed: false, reason: "The api key entry needs a reviewed non-empty name." };
|
|
3669
|
+
if (!Array.isArray(entry.origins) || entry.origins.length === 0 || !entry.origins.every((item) => ishttpsurl(item))) return { allowed: false, reason: "The api key needs a reviewed non-empty list of HTTPS origin scopes." };
|
|
3670
|
+
if (!isnonempty(entry.header)) return { allowed: false, reason: "The api key entry needs a reviewed non-empty header name." };
|
|
3671
|
+
if (typeof entry.value !== "string" || !entry.value) return { allowed: false, reason: "The api key needs its secret value in the reviewed options; it never enters the audit trail." };
|
|
3672
|
+
const consent = apikeyconsentgranted(step);
|
|
3673
|
+
if (!consent.allowed) return consent;
|
|
3674
|
+
}
|
|
3675
|
+
if (kind === "routeproxy") {
|
|
3676
|
+
if (!proxyrouteof(options.proxy)) return { allowed: false, reason: "A reviewed proxy route with scheme, host, port and a non-empty bypass list is required in options.proxy." };
|
|
3677
|
+
if (!isnonempty(options.consentref)) return { allowed: false, reason: "Proxy routing needs the explicit reviewed consent ref before any route applies." };
|
|
3678
|
+
}
|
|
3679
|
+
if (kind === "postform") {
|
|
3680
|
+
const form = formpayloadof(options.form);
|
|
3681
|
+
if (!form) return { allowed: false, reason: "A reviewed form payload with a url and a non-empty field list is required in options.form." };
|
|
3682
|
+
if (!ishttpsurl(form.url)) return { allowed: false, reason: "The form submission target must use HTTPS." };
|
|
3683
|
+
if (options.wait !== void 0 && (typeof options.wait !== "number" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: "The reviewed rate limit wait budget must be zero or a positive number of milliseconds." };
|
|
3684
|
+
}
|
|
3685
|
+
if (kind === "postfiles") {
|
|
3686
|
+
const upload = multipartpayloadof(options.upload);
|
|
3687
|
+
if (!upload) return { allowed: false, reason: "A reviewed multipart upload with a url and reviewed files is required in options.upload; every file carries the explicit reviewed flag." };
|
|
3688
|
+
if (!ishttpsurl(upload.url)) return { allowed: false, reason: "The multipart upload target must use HTTPS." };
|
|
3689
|
+
if (options.wait !== void 0 && (typeof options.wait !== "number" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: "The reviewed rate limit wait budget must be zero or a positive number of milliseconds." };
|
|
3690
|
+
}
|
|
3691
|
+
return { allowed: true };
|
|
3692
|
+
}
|
|
3693
|
+
function blockgate(session, step, now) {
|
|
3694
|
+
if (!session || session.stoppedat) return { allowed: false, reason: "No active browser session exists for the request block." };
|
|
3695
|
+
if (session.expiresat <= now) return { allowed: false, reason: "The browser session has expired and cannot block requests." };
|
|
3696
|
+
if (session.pausedat) return { allowed: false, reason: "The browser session is paused and cannot block requests." };
|
|
3697
|
+
let options = {};
|
|
3698
|
+
try {
|
|
3699
|
+
options = parseoptions(step);
|
|
3700
|
+
} catch {
|
|
3701
|
+
options = {};
|
|
3702
|
+
}
|
|
3703
|
+
const rule = options.block;
|
|
3704
|
+
if (!rule || typeof rule !== "object" || Array.isArray(rule) || rule.reviewed !== true) return { allowed: false, reason: "Request blocking needs its reviewed block rule with the explicit reviewed flag before any rule applies." };
|
|
3705
|
+
if (!blockruleof(rule)) return { allowed: false, reason: "The block rule needs a url pattern and an optional resource type list." };
|
|
3706
|
+
return { allowed: true };
|
|
3707
|
+
}
|
|
3708
|
+
function cookiegate(session, domain, now) {
|
|
3709
|
+
if (!session || session.stoppedat) return { allowed: false, reason: "No active browser session exists for the cookie operation." };
|
|
3710
|
+
if (session.expiresat <= now) return { allowed: false, reason: "The browser session has expired and cannot touch cookies." };
|
|
3711
|
+
if (session.pausedat) return { allowed: false, reason: "The browser session is paused and cannot touch cookies." };
|
|
3712
|
+
const grants = session.grants ?? [session.origin];
|
|
3713
|
+
if (!cookiedomaingranted(domain, grants)) return { allowed: false, reason: `The cookie domain ${domain} stays outside the session origin grants; cookie control refuses domains beyond the grants.` };
|
|
3714
|
+
return { allowed: true };
|
|
3715
|
+
}
|
|
3716
|
+
function proxygate(session, step, now) {
|
|
3717
|
+
if (!session || session.stoppedat) return { allowed: false, reason: "No active browser session exists for the proxy route." };
|
|
3718
|
+
if (session.expiresat <= now) return { allowed: false, reason: "The browser session has expired and cannot change routing." };
|
|
3719
|
+
if (session.pausedat) return { allowed: false, reason: "The browser session is paused and cannot change routing." };
|
|
3720
|
+
let options = {};
|
|
3721
|
+
try {
|
|
3722
|
+
options = parseoptions(step);
|
|
3723
|
+
} catch {
|
|
3724
|
+
options = {};
|
|
3725
|
+
}
|
|
3726
|
+
if (!isnonempty(options.consentref)) return { allowed: false, reason: "Proxy routing needs the explicit reviewed consent ref before any route applies." };
|
|
3727
|
+
if (!proxyrouteof(options.proxy)) return { allowed: false, reason: "The proxy route needs a scheme, host, port and a non-empty bypass list of origins that stay direct." };
|
|
3728
|
+
return { allowed: true };
|
|
3729
|
+
}
|
|
3730
|
+
function authconsentgranted(step) {
|
|
3731
|
+
let options = {};
|
|
3732
|
+
try {
|
|
3733
|
+
options = parseoptions(step);
|
|
3734
|
+
} catch {
|
|
3735
|
+
options = {};
|
|
3736
|
+
}
|
|
3737
|
+
const consentref = options.consentref;
|
|
3738
|
+
if (typeof consentref !== "string" || !consentref.trim()) return { allowed: false, reason: "An oauth flow requires the reviewed provider consent prompt ref in options before it starts." };
|
|
3739
|
+
return { allowed: true };
|
|
3740
|
+
}
|
|
3741
|
+
function apikeyconsentgranted(step) {
|
|
3742
|
+
let options = {};
|
|
3743
|
+
try {
|
|
3744
|
+
options = parseoptions(step);
|
|
3745
|
+
} catch {
|
|
3746
|
+
options = {};
|
|
3747
|
+
}
|
|
3748
|
+
const consentref = options.consentref;
|
|
3749
|
+
if (typeof consentref !== "string" || !consentref.trim()) return { allowed: false, reason: "Storing an api key requires the explicit reviewed consent prompt ref in options before anything is stored." };
|
|
3750
|
+
return { allowed: true };
|
|
3751
|
+
}
|
|
3752
|
+
function ratelimitbudgetallowed(wait, budget) {
|
|
3753
|
+
if (wait !== void 0 && (typeof wait !== "number" || !Number.isFinite(wait) || wait < 0)) return { allowed: false, reason: "The rate limit wait must be zero or a positive number of milliseconds." };
|
|
3754
|
+
if (budget !== void 0 && (typeof budget !== "number" || !Number.isFinite(budget) || budget < 0)) return { allowed: false, reason: "The reviewed rate limit budget must be zero or a positive number of milliseconds." };
|
|
3755
|
+
if (wait !== void 0 && budget !== void 0 && wait > budget) return { allowed: false, reason: `The rate limit wait of ${wait} milliseconds exceeds the reviewed budget of ${budget} milliseconds; review a wider budget or submit later.` };
|
|
3756
|
+
return { allowed: true };
|
|
3757
|
+
}
|
|
3758
|
+
function controltarget(step) {
|
|
3759
|
+
let options = {};
|
|
3760
|
+
try {
|
|
3761
|
+
options = parseoptions(step);
|
|
3762
|
+
} catch {
|
|
3763
|
+
options = {};
|
|
3764
|
+
}
|
|
3765
|
+
for (const key of ["form", "upload"]) {
|
|
3766
|
+
const value = options[key];
|
|
3767
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
3768
|
+
const url = value.url;
|
|
3769
|
+
if (typeof url === "string" && url.trim()) return url.trim();
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
if (step.kind === "authflow") {
|
|
3773
|
+
const flow = oauthflowof(options.oauth);
|
|
3774
|
+
if (flow) return flow.tokenurl;
|
|
3775
|
+
}
|
|
3776
|
+
return void 0;
|
|
3777
|
+
}
|
|
3233
3778
|
function sockettarget(step) {
|
|
3234
3779
|
let options = {};
|
|
3235
3780
|
try {
|
|
@@ -3611,6 +4156,10 @@ function validatestep(step, origin) {
|
|
|
3611
4156
|
const netwatchcheck = validatenetwatchgrammar(step, options);
|
|
3612
4157
|
if (!netwatchcheck.allowed) return netwatchcheck;
|
|
3613
4158
|
}
|
|
4159
|
+
if (iscontrolkind(step.kind)) {
|
|
4160
|
+
const controlcheck = validatecontrolgrammar(step, options);
|
|
4161
|
+
if (!controlcheck.allowed) return controlcheck;
|
|
4162
|
+
}
|
|
3614
4163
|
if (step.kind === "tabcreate") {
|
|
3615
4164
|
if (options.background !== void 0 && typeof options.background !== "boolean") return { allowed: false, reason: "The reviewed background flag must be a boolean." };
|
|
3616
4165
|
if (options.window !== void 0 && (typeof options.window !== "number" || !Number.isInteger(options.window) || options.window < 0)) return { allowed: false, reason: "The reviewed target window id must be a non-negative integer." };
|
|
@@ -3712,6 +4261,55 @@ function canexecute(input) {
|
|
|
3712
4261
|
const watchgatecheck = watchgate(input.session, input.settings, now);
|
|
3713
4262
|
if (!watchgatecheck.allowed) return watchgatecheck;
|
|
3714
4263
|
}
|
|
4264
|
+
if (iscontrolkind(input.step.kind)) {
|
|
4265
|
+
const controlgate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: "control the network" });
|
|
4266
|
+
if (!controlgate.allowed) return controlgate;
|
|
4267
|
+
let controloptions = {};
|
|
4268
|
+
try {
|
|
4269
|
+
controloptions = parseoptions(input.step);
|
|
4270
|
+
} catch {
|
|
4271
|
+
controloptions = {};
|
|
4272
|
+
}
|
|
4273
|
+
if (input.step.kind === "blockrequest") {
|
|
4274
|
+
const blockgatecheck = blockgate(input.session, input.step, now);
|
|
4275
|
+
if (!blockgatecheck.allowed) return blockgatecheck;
|
|
4276
|
+
const rule = blockruleof(controloptions.block);
|
|
4277
|
+
if (rule) {
|
|
4278
|
+
const blockorigin = origincheck(input.session, rule.urlpattern);
|
|
4279
|
+
if (!blockorigin.allowed) return blockorigin;
|
|
4280
|
+
}
|
|
4281
|
+
}
|
|
4282
|
+
if (input.step.kind === "mockresponse" || input.step.kind === "rewriteheaders") {
|
|
4283
|
+
const patterns = input.step.kind === "mockresponse" ? [mockspecof(controloptions.mock)?.urlpattern ?? ""] : Array.isArray(controloptions.rules) ? controloptions.rules.map((item) => item && typeof item === "object" && !Array.isArray(item) ? String(item.urlpattern ?? "") : "") : [];
|
|
4284
|
+
for (const pattern of patterns) {
|
|
4285
|
+
const patterngate = origincheck(input.session, pattern);
|
|
4286
|
+
if (!patterngate.allowed) return patterngate;
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
if (input.step.kind === "setcookies" || input.step.kind === "readcookies" || input.step.kind === "clearcookies") {
|
|
4290
|
+
const domain = typeof controloptions.domain === "string" && controloptions.domain.trim() ? controloptions.domain : Array.isArray(controloptions.cookies) ? String(controloptions.cookies[0]?.domain ?? "") : "";
|
|
4291
|
+
if (!domain) return { allowed: false, reason: "A reviewed cookie domain is required before cookie control runs." };
|
|
4292
|
+
const cookiegatecheck = cookiegate(input.session, domain, now);
|
|
4293
|
+
if (!cookiegatecheck.allowed) return cookiegatecheck;
|
|
4294
|
+
}
|
|
4295
|
+
if (input.step.kind === "authflow") {
|
|
4296
|
+
const authconsent = authconsentgranted(input.step);
|
|
4297
|
+
if (!authconsent.allowed) return authconsent;
|
|
4298
|
+
}
|
|
4299
|
+
if (input.step.kind === "saveapikey") {
|
|
4300
|
+
const keyconsent = apikeyconsentgranted(input.step);
|
|
4301
|
+
if (!keyconsent.allowed) return keyconsent;
|
|
4302
|
+
}
|
|
4303
|
+
if (input.step.kind === "routeproxy") {
|
|
4304
|
+
const proxygatecheck = proxygate(input.session, input.step, now);
|
|
4305
|
+
if (!proxygatecheck.allowed) return proxygatecheck;
|
|
4306
|
+
}
|
|
4307
|
+
const target = controltarget(input.step);
|
|
4308
|
+
if (target !== void 0) {
|
|
4309
|
+
const targetgate = origincheck(input.session, target);
|
|
4310
|
+
if (!targetgate.allowed) return targetgate;
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
3715
4313
|
if (input.step.kind === "extractapi") {
|
|
3716
4314
|
let replayoptions = {};
|
|
3717
4315
|
try {
|
|
@@ -3746,7 +4344,7 @@ function canexecute(input) {
|
|
|
3746
4344
|
}
|
|
3747
4345
|
|
|
3748
4346
|
// version.ts
|
|
3749
|
-
var packageversion = "1.1.
|
|
4347
|
+
var packageversion = "1.1.44";
|
|
3750
4348
|
|
|
3751
4349
|
// types.ts
|
|
3752
4350
|
var protocolversion = packageversion;
|
|
@@ -3783,6 +4381,27 @@ function parseproposal(value, origin, grants) {
|
|
|
3783
4381
|
...typeof candidate.value === "string" ? { value: candidate.value } : {},
|
|
3784
4382
|
...typeof candidate.options === "string" ? { options: candidate.options } : {}
|
|
3785
4383
|
};
|
|
4384
|
+
if (step.kind === "blockrequest") {
|
|
4385
|
+
let blockoptions = {};
|
|
4386
|
+
try {
|
|
4387
|
+
blockoptions = parseoptions(step);
|
|
4388
|
+
} catch {
|
|
4389
|
+
blockoptions = {};
|
|
4390
|
+
}
|
|
4391
|
+
const rule = blockruleof(blockoptions.block);
|
|
4392
|
+
if (rule && patternorigin(rule.urlpattern) === void 0) throw new Error("Block rules without a named origin pattern are refused.");
|
|
4393
|
+
}
|
|
4394
|
+
if (step.kind === "routeproxy") {
|
|
4395
|
+
let proxyoptions = {};
|
|
4396
|
+
try {
|
|
4397
|
+
proxyoptions = parseoptions(step);
|
|
4398
|
+
} catch {
|
|
4399
|
+
proxyoptions = {};
|
|
4400
|
+
}
|
|
4401
|
+
const proxy = proxyoptions.proxy;
|
|
4402
|
+
const bypass = proxy && typeof proxy === "object" && !Array.isArray(proxy) ? proxy.bypass : void 0;
|
|
4403
|
+
if (!Array.isArray(bypass) || bypass.length === 0) throw new Error("Proxy routes without a bypass list are refused.");
|
|
4404
|
+
}
|
|
3786
4405
|
const evaluation = validatestep(step, origin);
|
|
3787
4406
|
if (!evaluation.allowed) throw new Error(evaluation.reason);
|
|
3788
4407
|
const target = outboundtarget(step);
|
|
@@ -3857,7 +4476,7 @@ function requestbody(input) {
|
|
|
3857
4476
|
return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation, capabilities: input.capabilities });
|
|
3858
4477
|
}
|
|
3859
4478
|
function outcomeresponse(input) {
|
|
3860
|
-
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {}, ...input.media ? { media: input.media } : {}, ...input.transport ? { transport: input.transport } : {}, ...input.network ? { network: input.network } : {} });
|
|
4479
|
+
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {}, ...input.media ? { media: input.media } : {}, ...input.transport ? { transport: input.transport } : {}, ...input.network ? { network: input.network } : {}, ...input.control ? { control: input.control } : {} });
|
|
3861
4480
|
}
|
|
3862
4481
|
function mapresponse(input) {
|
|
3863
4482
|
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, map: input.map });
|
|
@@ -3951,12 +4570,36 @@ function callsreport(input) {
|
|
|
3951
4570
|
function exchangesreport(input) {
|
|
3952
4571
|
return { version: protocolversion, exchanges: input.exchanges, channels: input.channels, subscriptions: input.subscriptions, apimap: input.apimap };
|
|
3953
4572
|
}
|
|
4573
|
+
function authreport(input) {
|
|
4574
|
+
const tokens = input.tokens.map((token) => {
|
|
4575
|
+
const { accessstorageid, refreshstorageid, ...metadata } = token;
|
|
4576
|
+
void accessstorageid;
|
|
4577
|
+
void refreshstorageid;
|
|
4578
|
+
return metadata;
|
|
4579
|
+
});
|
|
4580
|
+
return { version: protocolversion, tokens };
|
|
4581
|
+
}
|
|
4582
|
+
function controlreport(input) {
|
|
4583
|
+
const mocks = input.mocks.map((spec) => {
|
|
4584
|
+
const { body, ...metadata } = spec;
|
|
4585
|
+
void body;
|
|
4586
|
+
return metadata;
|
|
4587
|
+
});
|
|
4588
|
+
return { version: protocolversion, blocks: input.blocks, mocks, rewrites: input.rewrites, cookies: input.cookies, proxies: input.proxies, ratelimits: input.ratelimits };
|
|
4589
|
+
}
|
|
3954
4590
|
export {
|
|
3955
4591
|
annotationplanof,
|
|
3956
4592
|
apientries,
|
|
4593
|
+
apikeyconsentgranted,
|
|
3957
4594
|
apireplayspecof,
|
|
4595
|
+
applyheaderules,
|
|
3958
4596
|
assetentries,
|
|
4597
|
+
authconsentgranted,
|
|
4598
|
+
authorizeurl,
|
|
4599
|
+
authreport,
|
|
3959
4600
|
blendrows,
|
|
4601
|
+
blockgate,
|
|
4602
|
+
blockruleof,
|
|
3960
4603
|
bodyfilterof,
|
|
3961
4604
|
bodymatches,
|
|
3962
4605
|
buildname,
|
|
@@ -3968,6 +4611,7 @@ export {
|
|
|
3968
4611
|
callsreport,
|
|
3969
4612
|
canexecute,
|
|
3970
4613
|
capturebody,
|
|
4614
|
+
capturecode,
|
|
3971
4615
|
capturedheaders,
|
|
3972
4616
|
captureelement,
|
|
3973
4617
|
captureformats,
|
|
@@ -3983,7 +4627,13 @@ export {
|
|
|
3983
4627
|
channelorigin,
|
|
3984
4628
|
closechannel,
|
|
3985
4629
|
collectmessages,
|
|
4630
|
+
controlkinds,
|
|
4631
|
+
controlreport,
|
|
4632
|
+
controltarget,
|
|
3986
4633
|
convertdirectiveof,
|
|
4634
|
+
cookiedomaingranted,
|
|
4635
|
+
cookiegate,
|
|
4636
|
+
cookierecordof,
|
|
3987
4637
|
correlationid,
|
|
3988
4638
|
croprect,
|
|
3989
4639
|
crossesviewport,
|
|
@@ -4004,12 +4654,14 @@ export {
|
|
|
4004
4654
|
filterexchanges,
|
|
4005
4655
|
finishrecording,
|
|
4006
4656
|
fixedheadermatch,
|
|
4657
|
+
formpayloadof,
|
|
4007
4658
|
formreportresponse,
|
|
4008
4659
|
frameinterval,
|
|
4009
4660
|
generatedvalueallowed,
|
|
4010
4661
|
graphqlopenvelope,
|
|
4011
4662
|
graphqlrequestof,
|
|
4012
4663
|
headerfilterof,
|
|
4664
|
+
headeruleof,
|
|
4013
4665
|
heldkeysreport,
|
|
4014
4666
|
hostpattern,
|
|
4015
4667
|
htmlqueriesof,
|
|
@@ -4017,6 +4669,7 @@ export {
|
|
|
4017
4669
|
imagefilterof,
|
|
4018
4670
|
imagematches,
|
|
4019
4671
|
imagenames,
|
|
4672
|
+
iscontrolkind,
|
|
4020
4673
|
isformkind,
|
|
4021
4674
|
isnetwatchkind,
|
|
4022
4675
|
issocketkind,
|
|
@@ -4027,17 +4680,26 @@ export {
|
|
|
4027
4680
|
layoutreport,
|
|
4028
4681
|
mapresponse,
|
|
4029
4682
|
matchmessage,
|
|
4683
|
+
matchurlpattern,
|
|
4030
4684
|
mediaentries,
|
|
4031
4685
|
mediakinds,
|
|
4032
4686
|
mediareport,
|
|
4033
4687
|
messagefilterof,
|
|
4688
|
+
mockfor,
|
|
4689
|
+
mockspecof,
|
|
4690
|
+
multipartchunks,
|
|
4691
|
+
multipartpayloadof,
|
|
4034
4692
|
navstateresponse,
|
|
4035
4693
|
netlogreport,
|
|
4036
4694
|
netwatchkinds,
|
|
4695
|
+
newblockrule,
|
|
4037
4696
|
newchannel,
|
|
4038
4697
|
newexchange,
|
|
4698
|
+
newheaderule,
|
|
4699
|
+
newmockspec,
|
|
4039
4700
|
newrecording,
|
|
4040
4701
|
normalizeendpoint,
|
|
4702
|
+
oauthflowof,
|
|
4041
4703
|
observationmodeof,
|
|
4042
4704
|
observationresponse,
|
|
4043
4705
|
openchannel,
|
|
@@ -4047,7 +4709,9 @@ export {
|
|
|
4047
4709
|
parsehtmlbody,
|
|
4048
4710
|
parseproposal,
|
|
4049
4711
|
parsessetext,
|
|
4712
|
+
parsetokens,
|
|
4050
4713
|
passwordconsentgranted,
|
|
4714
|
+
patternorigin,
|
|
4051
4715
|
payloadshapeof,
|
|
4052
4716
|
payloadvalid,
|
|
4053
4717
|
payloadwithdefaults,
|
|
@@ -4062,21 +4726,30 @@ export {
|
|
|
4062
4726
|
profilegrantgranted,
|
|
4063
4727
|
protocolversion,
|
|
4064
4728
|
provenancereport,
|
|
4729
|
+
proxygate,
|
|
4730
|
+
proxyrouteof,
|
|
4065
4731
|
publishmessage,
|
|
4066
4732
|
quarantinereport,
|
|
4067
4733
|
randomid,
|
|
4068
4734
|
rankapis,
|
|
4735
|
+
ratelimitbudgetallowed,
|
|
4736
|
+
ratelimitreadof,
|
|
4737
|
+
ratelimitwait,
|
|
4069
4738
|
readpath,
|
|
4070
4739
|
readstream,
|
|
4071
4740
|
receivemessage,
|
|
4072
4741
|
reconnectwaits,
|
|
4073
4742
|
recordingoptionsof,
|
|
4743
|
+
redactedcookies,
|
|
4074
4744
|
regionsteps,
|
|
4075
4745
|
replayurl,
|
|
4076
4746
|
requestbody,
|
|
4077
4747
|
resolutionverdict,
|
|
4078
4748
|
resolvedrisk,
|
|
4079
4749
|
resourcefacts,
|
|
4750
|
+
retryafterof,
|
|
4751
|
+
revertrule,
|
|
4752
|
+
revocationruleof,
|
|
4080
4753
|
safetyresponse,
|
|
4081
4754
|
scaledrect,
|
|
4082
4755
|
seamweights,
|
|
@@ -4097,9 +4770,11 @@ export {
|
|
|
4097
4770
|
templateurl,
|
|
4098
4771
|
thumbdirectiveof,
|
|
4099
4772
|
thumbgeometry,
|
|
4773
|
+
tokenrequest,
|
|
4100
4774
|
trailreport,
|
|
4101
4775
|
transformgrammar,
|
|
4102
4776
|
unwrapgraphql,
|
|
4777
|
+
urlencodeform,
|
|
4103
4778
|
validatefieldmatch,
|
|
4104
4779
|
validateformrecord,
|
|
4105
4780
|
validatestep,
|