@f5-sales-demo/xcsh 23.2.2 → 23.3.3
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/package.json +8 -8
- package/src/commands/blindfold-args.ts +16 -3
- package/src/commands/blindfold-help.ts +2 -2
- package/src/commands/blindfold.ts +2 -2
- package/src/internal-urls/build-info.generated.ts +8 -8
- package/src/internal-urls/docs-index.generated.ts +2 -1
- package/src/internal-urls/public-citation-destinations.generated.ts +2 -2
- package/src/internal-urls/terraform-documentation-assets.generated.ts +28 -28
- package/src/internal-urls/terraform-documentation.ts +1 -1
- package/src/internal-urls/terraform-property-index.ts +14 -1
- package/src/internal-urls/terraform-property-ranking.ts +10 -3
- package/src/internal-urls/terraform-provider-pin.generated.ts +1 -1
- package/src/prompts/tools/xcsh-blindfold.md +1 -1
- package/src/services/blindfold-contract/blindfold-contract-v1.txt +1 -0
- package/src/services/blindfold-contract/lock.json +6 -0
- package/src/services/blindfold-documents.ts +1 -12
- package/src/services/blindfold-ensure.ts +428 -0
- package/src/services/blindfold.ts +16 -6
- package/src/terraform-documentation-smoke.ts +2 -2
- package/src/terraform-port-smoke.ts +15 -0
- package/src/tools/xcsh-blindfold.ts +6 -1
|
@@ -7,55 +7,55 @@ export const EMBEDDED_TERRAFORM_DOCUMENTATION = {
|
|
|
7
7
|
pin: {
|
|
8
8
|
assets: {
|
|
9
9
|
"canonical-documentation.tar.gz": {
|
|
10
|
-
sha256: "
|
|
11
|
-
size_bytes:
|
|
10
|
+
sha256: "a587ffe7493a3ff798f04fffaf8c44e5bade4d4db7a87d37a057db76e520251e",
|
|
11
|
+
size_bytes: 46290029,
|
|
12
12
|
},
|
|
13
13
|
"canonical-manifest.json": {
|
|
14
|
-
sha256: "
|
|
15
|
-
size_bytes:
|
|
14
|
+
sha256: "6546cdca2376316f908d8745f794f62c66928bd9641ac45ee23e709dffc2e11d",
|
|
15
|
+
size_bytes: 7563114,
|
|
16
16
|
},
|
|
17
17
|
"manifest.json": {
|
|
18
|
-
sha256: "
|
|
19
|
-
size_bytes:
|
|
18
|
+
sha256: "814cd61535ef17b4cac5738255561570514fc10f7ccdc9e8248047d1712a1dac",
|
|
19
|
+
size_bytes: 70455788,
|
|
20
20
|
},
|
|
21
21
|
"publication.json": {
|
|
22
|
-
sha256: "
|
|
23
|
-
size_bytes:
|
|
22
|
+
sha256: "85969acba54f14a657841a31a3096891561aba4f9f5aff21859c64e0123585d3",
|
|
23
|
+
size_bytes: 1378,
|
|
24
24
|
},
|
|
25
25
|
"registry-documentation.tar.gz": {
|
|
26
|
-
sha256: "
|
|
27
|
-
size_bytes:
|
|
26
|
+
sha256: "07c5f0966bdf96ff29e5d67bd1d0b7a4e4a7ab8a22cec79602bfadf59874ecbe",
|
|
27
|
+
size_bytes: 9973786,
|
|
28
28
|
},
|
|
29
29
|
"registry-manifest.json": {
|
|
30
|
-
sha256: "
|
|
31
|
-
size_bytes:
|
|
30
|
+
sha256: "754d4c76e43ab0dbd0192cd4f3719b882561ccd6813b17b9eea548cee1fe4826",
|
|
31
|
+
size_bytes: 236413,
|
|
32
32
|
},
|
|
33
33
|
"registry-projection-manifest.json": {
|
|
34
|
-
sha256: "
|
|
35
|
-
size_bytes:
|
|
34
|
+
sha256: "37a17468c18c89d6bd7866ef56a711fed2f159a5ba71189c2017c452b9ed98d3",
|
|
35
|
+
size_bytes: 275841,
|
|
36
36
|
},
|
|
37
|
-
SHA256SUMS: { sha256: "
|
|
37
|
+
SHA256SUMS: { sha256: "7c39040e0deb88a6d64632f64d537495c8431d0da7bbf708c272953d8be533bb", size_bytes: 723 },
|
|
38
38
|
"terraform-docs.tar.gz": {
|
|
39
|
-
sha256: "
|
|
40
|
-
size_bytes:
|
|
39
|
+
sha256: "1ef05c0b53548862e70f9886845e6533deddd0b5823b4fe149aa919edf2f725f",
|
|
40
|
+
size_bytes: 9851591,
|
|
41
41
|
},
|
|
42
42
|
},
|
|
43
|
-
document_count:
|
|
44
|
-
provider_schema_digest: "sha256:
|
|
45
|
-
provider_version: "v15.
|
|
46
|
-
release_tag: "documentation-v15.
|
|
43
|
+
document_count: 16396,
|
|
44
|
+
provider_schema_digest: "sha256:7e724befbd28dae1d544e2cc8bbc72d0e62fdd0382374fb6e98044bf0ff0e829",
|
|
45
|
+
provider_version: "v15.6.1",
|
|
46
|
+
release_tag: "documentation-v15.6.1",
|
|
47
47
|
retrieval_metadata_version: 1,
|
|
48
48
|
schema_version: 2,
|
|
49
|
-
source_commit: "
|
|
49
|
+
source_commit: "aebd99b5d6d36211be377a25798c43166de38d01",
|
|
50
50
|
source_repository: "f5-sales-demo/terraform-provider-xcsh",
|
|
51
51
|
source_root: "documentation",
|
|
52
|
-
spec_pin_digest: "sha256:
|
|
53
|
-
receipt_sha256: "
|
|
52
|
+
spec_pin_digest: "sha256:e06a3ea9db6a533295efd5c7a477afc65990ba80c3a998885b97b47262cfe9f1",
|
|
53
|
+
receipt_sha256: "85969acba54f14a657841a31a3096891561aba4f9f5aff21859c64e0123585d3",
|
|
54
54
|
index: {
|
|
55
|
-
sha256: "
|
|
56
|
-
size_bytes:
|
|
57
|
-
gzip_sha256: "
|
|
58
|
-
gzip_size_bytes:
|
|
55
|
+
sha256: "90e26db52b73fdf40f6c9fa847cfdf3de99f1aa17de642f8405a1c6f0e0f90bb",
|
|
56
|
+
size_bytes: 667938816,
|
|
57
|
+
gzip_sha256: "a614a0e18c8482bf447c3436511314ec10f53960ebda7d761cf897d98cfe7b33",
|
|
58
|
+
gzip_size_bytes: 63442781,
|
|
59
59
|
},
|
|
60
60
|
},
|
|
61
61
|
} satisfies TerraformEmbeddedAssets;
|
|
@@ -2066,7 +2066,7 @@ export class TerraformDocumentationRepository {
|
|
|
2066
2066
|
db
|
|
2067
2067
|
.query(`SELECT 1 FROM terraform_aliases WHERE ${aliasClauses.join(" AND ")} LIMIT 1`)
|
|
2068
2068
|
.get(...aliasValues);
|
|
2069
|
-
if (!genericConfigure || (ranked.
|
|
2069
|
+
if (!genericConfigure || (ranked.some(row => row.score > 0) && !aliasNavigation)) {
|
|
2070
2070
|
if (ranked[0]?.anchor === "section" && !propertyRequestsBlock(search)) {
|
|
2071
2071
|
const record = db
|
|
2072
2072
|
.query("SELECT metadata FROM terraform_documents WHERE path=?")
|
|
@@ -270,6 +270,13 @@ export function searchPropertyIndex(
|
|
|
270
270
|
if (propertyInvalidExcludedScope(query)) return [];
|
|
271
271
|
const terms = propertyQueryTerms(query);
|
|
272
272
|
if (!terms.length) return [];
|
|
273
|
+
const knownTerms = new Set(
|
|
274
|
+
(
|
|
275
|
+
db
|
|
276
|
+
.prepare(`SELECT DISTINCT term FROM property_scope_terms WHERE term IN (${terms.map(() => "?").join(",")})`)
|
|
277
|
+
.all(...terms) as { term: string }[]
|
|
278
|
+
).map(row => row.term),
|
|
279
|
+
);
|
|
273
280
|
const clauses = ["property_search MATCH ?"];
|
|
274
281
|
const args: string[] = [terms.map(term => `"${term}"`).join(" OR ")];
|
|
275
282
|
if (scope.schemaPaths?.length) {
|
|
@@ -399,7 +406,13 @@ export function searchPropertyIndex(
|
|
|
399
406
|
aliasTerms: JSON.parse(alias_terms) as string[],
|
|
400
407
|
}),
|
|
401
408
|
);
|
|
402
|
-
ranked.push(
|
|
409
|
+
ranked.push(
|
|
410
|
+
...rankPropertyScope(query, {
|
|
411
|
+
rows,
|
|
412
|
+
weights: new Map(weights.map(row => [row.term, row.weight])),
|
|
413
|
+
knownTerms,
|
|
414
|
+
}),
|
|
415
|
+
);
|
|
403
416
|
}
|
|
404
417
|
return ranked.sort(
|
|
405
418
|
(a, b) =>
|
|
@@ -15,7 +15,7 @@ export interface PropertyCandidate {
|
|
|
15
15
|
documentation_terms?: string[];
|
|
16
16
|
}
|
|
17
17
|
const stop = new Set(
|
|
18
|
-
"a an the and to of for in on with by as from at we our my your i how which what where can do does is are be been have has it this that its resource managed provider terraform field attribute property parameter configure configures configuration configuring defining define declares declare declaring specified specifies specify sets set setting outputs output generated existing list string boolean block schema using use when need".split(
|
|
18
|
+
"a an the and to of for in on with by as from at we our my your i how which what where can do does is are be been have has it this that its resource managed provider terraform field attribute property parameter configure configures configuration configuring defining define declares declare declaring specified specifies specify sets set put setting outputs output generated existing list string boolean block schema using use when need".split(
|
|
19
19
|
" ",
|
|
20
20
|
),
|
|
21
21
|
);
|
|
@@ -816,7 +816,7 @@ export function preparePropertyScope(rows: readonly PropertyCandidate[]) {
|
|
|
816
816
|
}
|
|
817
817
|
export function rankPropertyScope(
|
|
818
818
|
queryText: string,
|
|
819
|
-
scope: ReturnType<typeof preparePropertyScope
|
|
819
|
+
scope: ReturnType<typeof preparePropertyScope> & { knownTerms?: ReadonlySet<string> },
|
|
820
820
|
candidates?: ReadonlySet<string>,
|
|
821
821
|
) {
|
|
822
822
|
const providerTerms = new Set(propertyTerms(scope.rows[0]?.provider_name ?? ""));
|
|
@@ -831,6 +831,8 @@ export function rankPropertyScope(
|
|
|
831
831
|
const target = propertyQueryTerms(ask).filter(t => !providerTerms.has(t) || requested.has(t));
|
|
832
832
|
const requestedType = propertyRequestedType(queryText);
|
|
833
833
|
const access = requestedFieldAccess(queryText);
|
|
834
|
+
const missingWeight = Math.max(1, ...scope.weights.values());
|
|
835
|
+
const missingConcepts = new Set(target.filter(term => scope.knownTerms?.has(term) && !scope.weights.has(term)));
|
|
834
836
|
return scope.rows
|
|
835
837
|
.filter(row => matchesFieldAccess(row, access))
|
|
836
838
|
.filter(row => propertyMatchesCookieOperators(queryText, row))
|
|
@@ -840,7 +842,9 @@ export function rankPropertyScope(
|
|
|
840
842
|
.filter(row => !requestedType || row.type == null || row.type === requestedType)
|
|
841
843
|
.filter(row => !candidates || candidates.has(`${row.path}#${row.anchor}`))
|
|
842
844
|
.map(row => {
|
|
843
|
-
const
|
|
845
|
+
const documentationTerms = new Set(row.documentation_terms ?? []);
|
|
846
|
+
const weight = (term: string) =>
|
|
847
|
+
scope.weights.get(term) ?? (missingConcepts.has(term) && !documentationTerms.has(term) ? missingWeight : 0);
|
|
844
848
|
const union = new Set([...row.leaf, ...row.context, ...row.descriptionTerms, ...row.aliasTerms]);
|
|
845
849
|
let coverage = 0,
|
|
846
850
|
total = 0,
|
|
@@ -947,6 +951,9 @@ export function rankPropertyScope(
|
|
|
947
951
|
!union.has(positive!)
|
|
948
952
|
)
|
|
949
953
|
score -= 30;
|
|
954
|
+
// A leaf-name bonus cannot compensate for concepts absent from the
|
|
955
|
+
// provider scope. Keep all ranking terms proportional to coverage.
|
|
956
|
+
if (score > 0 && total > 0 && missingConcepts.size) score *= coverage / total;
|
|
950
957
|
const {
|
|
951
958
|
leaf: _leaf,
|
|
952
959
|
context: _context,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by generate-terraform-documentation-index.ts from the reviewed build-time pin.
|
|
2
|
-
export const EMBEDDED_PROVIDER_VERSION = "15.
|
|
2
|
+
export const EMBEDDED_PROVIDER_VERSION = "15.6.1";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
Encrypt local secret files or PEM/PKCS#12 certificate keys with the tenant Blindfold public key. Operations: public-key, policy, encrypt, certificate, create, replace. Create fails on collision; replace rotates an existing certificate and preserves other options. Use file paths only. PassphraseEnv names an existing environment variable; never put a key, passphrase or token in arguments. outputFile is required for encrypt and certificate preparation. outputFile and resultFile must name new files. Results contain public status, target, fingerprint and paths only. API acceptance does not prove TLS readiness. Plan Mode blocks deployment and artifact writing. Select and verify the intended context before deployment.
|
|
1
|
+
Encrypt local secret files or PEM/PKCS#12 certificate keys with the tenant Blindfold public key. Operations: public-key, policy, encrypt, certificate, create, replace, ensure. Create fails on collision; replace rotates an existing certificate and preserves other options. Ensure reuses unchanged ciphertext and accepts a version 1 manifest through file. Use file paths only. PassphraseEnv names an existing environment variable; never put a key, passphrase or token in arguments. outputFile is required for encrypt and certificate preparation. outputFile and resultFile must name new files. Results contain public status, target, fingerprint and paths only. API acceptance does not prove TLS readiness. Plan Mode blocks deployment and artifact writing. Select and verify the intended context before deployment.
|
|
2
2
|
|
|
3
3
|
For offline encryption, supply both publicKey and policyDocument file paths with an input file path and outputFile. These paths contain public JSON/YAML documents; encryption requires no context or credentials. Never supply stdin or inline material.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"files":{"fixtures/pinned-reference.json":"{\n \"image\": \"kreynoldsf5/vesctl@sha256:6ef8dc145b53130273bca4d3400ff9349e057ae36ed8e36d943eb1465e7edd82\",\n \"version\": \"0-2-24\",\n \"location\": \"string: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\"\n}\n","fixtures/synthetic-inputs.json":"{\n \"ambiguous.p12\": \"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\",\n \"ec-key.pem\": \"LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ3YyK0pEckc4UldYK2dmSk0KbGNuZ0ZtN3ova3ZNVzBoMGx0TDRWTlJsWnh1aFJBTkNBQVIvTzdLcjY1WTRoUjAwTWpTNXN6U01NZCtOK2JQTwovTFNzRjNGR0toRGhiaXd2NXhLQVh6R3V2bE5EYmZ3aFlGdkRGay9scjNFbEl6Zk1xVW9ITUNoTwotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==\",\n \"ec-protected.pem\": \"LS0tLS1CRUdJTiBFTkNSWVBURUQgUFJJVkFURSBLRVktLS0tLQpNSUhzTUZjR0NTcUdTSWIzRFFFRkRUQktNQ2tHQ1NxR1NJYjNEUUVGRERBY0JBanA5cm1QSDdhSEZ3SUNDQUF3CkRBWUlLb1pJaHZjTkFna0ZBREFkQmdsZ2hrZ0JaUU1FQVNvRUVLTXZWUENCd0lEUi9WYVlCd2dnWjU4RWdaQ2YKZWtwQlM4U2FZMGppdExFbEE5OHRDZmtmL2phUHhiZzdCUWxmblFwaUlLSGYzampidWJEdFZDYXRuVEljbDRiYQppQW0zRjdMaCtPNXJJZVExWGxjOVd4blNsTVhFbkhBb1orc1Jua0FuK090SzNEVWNzcGladGNYeFo3eUhPTWlKCklqbGVqNGtZdTVBdldRYjE3dGVYRjFDWEtoNHl2b0ZneEtRb0RPZGJwaUY4VlYydGtDUlZMYnBVOFQra1VsYz0KLS0tLS1FTkQgRU5DUllQVEVEIFBSSVZBVEUgS0VZLS0tLS0K\",\n \"ec.p12\": \"MIIEHQIBAzCCA9cGCSqGSIb3DQEHAaCCA8gEggPEMIIDwDCCAmIGCSqGSIb3DQEHBqCCAlMwggJPAgEAMIICSAYJKoZIhvcNAQcBMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgrw9EXz0BS+wICTiAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEIcXZur7HMtDEzZyK0/mavCAggHgafbtXJNkIMdRdsvd2HK4HDWeKGtE2PcscylE288xt6pEEx2JQwHkFaIeeaTeuoUryxj51t8u4KUJYy+7k8byy/w3GUE1YpstgjZW2h0vYDcIt3nGPdi5FOIDNbmJgpLKWdqSaA6s8kNKov5MBgtQoDvccIS0yrCgSJsG+XsZxWXVJBm9XlIsNHMCwETSabcHhTDurxS0nIsMA9hoayAXysAc8Nmc0WS11kijdzQxft2RgABq8vRUJSNLL8O1JlJjHMrqv1gc8otDPmJrVIH9xkL/LiYzKGUM9ov6H4CDifcfhWKMBjILk88hn52Tg0V/6DXId1R1H40qlJ9U4bDSUBHbC3V6ZWTPeA3GnrgvDU3GA2O6P+raqnPv1g/1IaS3KvhQi2eVAnO0oeFSK3uLvPaqwRg/60t0S4Z51kQYQdJgk5iJmXKXkQKZGxjUeq4ylkmDfbkQm/eba/UZK8CoOQpZtDKCQ9UMSpbVEB0uVRStZe08j4WmlMMlt9yySZr0MpkwhZgc49ZvzcngOU64EMV9n8pUDXtd/mIF76K23NxcO+r2jRxQ/vL12n1sf7SHE8u5qtFHiBCxhk4OBZ+zLIwP2HbqyL9lkINiWEH7FtHtOXaSYeVLXWROyLr+FyupMIIBVgYJKoZIhvcNAQcBoIIBRwSCAUMwggE/MIIBOwYLKoZIhvcNAQwKAQKgge8wgewwVwYJKoZIhvcNAQUNMEowKQYJKoZIhvcNAQUMMBwECJtUGP9+vKP0AgJOIDAMBggqhkiG9w0CCQUAMB0GCWCGSAFlAwQBKgQQVfrU2iCkELrqK0IlUR6M8gSBkKwU2F/IXnVqxBrt1m/90Ju11r+uz+X5GK53GSQ9BMZzupJr2GgCpgRv5Swv2q8I9rxOGdHBcOrHWh0omduEZsNOI4VVAJFq539MlpVSQLbEIce+KVDv2afcyrevvcFz+E6pGStD6g1F4oNBwam6Y5b6MKmQ/H+nwDjGGlE10P9AwpBcIbM3NRjpszroZEpXOzE6MBMGCSqGSIb3DQEJFDEGHgQAZQBjMCMGCSqGSIb3DQEJFTEWBBRw3AxVhnKhk4jdPzq/g+CFjfKYsjA9MDEwDQYJYIZIAWUDBAIBBQAEINiUDqO+Ipik80DDUyw9hWCp0EnT/SzkMeWHtL4lNlTbBAiQ1ErGx9Waxg==\",\n \"ec.pem\": \"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJhakNDQVJHZ0F3SUJBZ0lVUWFrekpTUExlVVVWTERQYXN5eStIN2NTYjE4d0NnWUlLb1pJemowRUF3SXcKSVRFZk1CMEdBMVVFQXd3V1lteHBibVJtYjJ4a0xtVjRZVzF3YkdVdWRHVnpkREFnRncweU1EQXhNREV3TURBdwpNREJhR0E4eU1EazVNREV3TVRBd01EQXdNRm93SVRFZk1CMEdBMVVFQXd3V1lteHBibVJtYjJ4a0xtVjRZVzF3CmJHVXVkR1Z6ZERCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkg4N3NxdnJsamlGSFRReU5MbXoKTkl3eDM0MzVzODc4dEt3WGNVWXFFT0Z1TEMvbkVvQmZNYTYrVTBOdC9DRmdXOE1XVCtXdmNTVWpOOHlwU2djdwpLRTZqSlRBak1DRUdBMVVkRVFRYU1CaUNGbUpzYVc1a1ptOXNaQzVsZUdGdGNHeGxMblJsYzNRd0NnWUlLb1pJCnpqMEVBd0lEUndBd1JBSWdQV2ZKaHFWbVl5NlRGM3kzSmZtRkNIcWc3U1ZtVHR1ZHYrZG14Nzl6cHBNQ0lDZVYKSjFSclNGNkQvOGNUTVdnbGRta25DTmVMOUlvdXplZUtvUTZYbXRoVgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==\",\n \"expired.pem\": \"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN0ekNDQVorZ0F3SUJBZ0lCS2pBTkJna3Foa2lHOXcwQkFRc0ZBREFmTVIwd0d3WURWUVFEREJSbGVIQnAKY21Wa0xtVjRZVzF3YkdVdWRHVnpkREFlRncweU1EQXhNREV3TURBd01EQmFGdzB5TVRBeE1ERXdNREF3TURCYQpNQjh4SFRBYkJnTlZCQU1NRkdWNGNHbHlaV1F1WlhoaGJYQnNaUzUwWlhOME1JSUJJakFOQmdrcWhraUc5dzBCCkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXRXUm5CbFQ1VVNmWkUvL2pwWWFlT2lzK3A0TjM4dHNEZnovYmxod1oKVnI4c1NpdzZVRkREZmpJakh6U29yeWZYN2c4Z2NaY3VzSlY1ZEd6UzEvalVHZ2NiN1NKSmJlTkhWTzNnUFhuQwp0TngzVDQ0d1h4Wk1PWVBpUWo3cEhNTFFuT1FZKy95dUk4UXp6THhkS1JMdXhLRWx6cDJlclg3VWNXZGxMdzRqCllXVDhEdDBHa2VReHo3VkQ2SWlMYjVyeCtiOWxYbGpUYW8zQjFXWnBPMlc0aW1RaVZ5bUtRQ3VNK1p0anNTRWQKUHBhVmNmTENabXlqK1N2RHJlYWd0QWhoTDdrZVNnbVIwbGp2ZGRGeFptUnVDNzVVNHFVRmRFQ3ltWnVrTTd2QwpraFd1OTFWYmdtSWpzZjRyeGlxZzVzK2RoRC8yR1dTRzJLc3JtVFpobWZtWjhRSURBUUFCTUEwR0NTcUdTSWIzCkRRRUJDd1VBQTRJQkFRQUNHZWlYdzJpYjlwcWVYdmN4Y2RvcW9vK3JkaUsrbm1GZVFiQlAyd0pVRzRXUk5WSEwKMkw1OERQeGQ0TGh3aWJwdyt4SHl3cTJ6K0NpYzNrdFBSU21JMUNTRXlUcFhXM2hUa2w1QU1jd252RjJMOWtCUAp6QzJZMDFQcThCeHlqTEFXSnhWenRQT0w4bjg5bDk3YWZObmxCallzdGJkTVVvaEFaeFJUSlJaVmdkZUJ3c0NqCkRFQ1pIV2ljeHRLU2dUWXR5R01pcitkRktGMm5mQWV3WG9CMHBNbFVtanNmS2dFOFExeStCa0FQcGdZZmRaY2YKeWhTYk9lcTczV0lJYWQxRmNNam05b3IzTFlnalhONm9vSVAyRDBVSlJvWmNMV3hWVlFUdFVxbmRYejJCbmlacQoyN0FqU2Z1YzFHYUlNZjhhblliSHZSYVp2OUNvZEwyVVN6blEKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=\",\n \"rsa-key.pem\": \"LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRQzFaR2NHVlBsUko5a1QKLytPbGhwNDZLejZuZzNmeTJ3Ti9QOXVXSEJsV3Z5eEtMRHBRVU1OK01pTWZOS2l2SjlmdUR5QnhseTZ3bFhsMApiTkxYK05RYUJ4dnRJa2x0NDBkVTdlQTllY0swM0hkUGpqQmZGa3c1ZytKQ1B1a2N3dENjNUJqNy9LNGp4RFBNCnZGMHBFdTdFb1NYT25aNnRmdFJ4WjJVdkRpTmhaUHdPM1FhUjVESFB0VVBvaUl0dm12SDV2MlZlV05OcWpjSFYKWm1rN1piaUtaQ0pYS1lwQUs0ejVtMk94SVIwK2xwVng4c0ptYktQNUs4T3Q1cUMwQ0dFdnVSNUtDWkhTV085MQowWEZtWkc0THZsVGlwUVYwUUxLWm02UXp1OEtTRmE3M1ZWdUNZaU94L2l2R0txRG16NTJFUC9ZWlpJYllxeXVaCk5tR1orWm54QWdNQkFBRUNnZ0VBSFVEUEcvdlBPM0hZTmVhbmhzQ0NPd2VuWFQrUlhzYWR0cGkzVXBXVWdUaTkKTFV4d1dSYzFUVFdoRkJMR0tOS2RwYm1seTFFM2lUM2ZRNmRGNGo1Y1Y4TG12am13Z0RyT1VhN2lqT0l2N3UxbQpobkRSY2ViNExiRzNFYnBGNjZBQUliL29IRUlMV1hSTHdFeHVkUnNsdGtDZzNCbnZzYk9KdlFJN2xMajNKcjVyCmFKaGl5YVl0THErVDBtVW5TbFpYdUJMTjB5cjhWb2IrYUt4NXZneHNuME4rOU9GdU9Fbk1WQmZBYUdtdWF0OUEKQ0VQVW1TV1FwVVZMT2pNenJrTWRUbzQwcEZtN0o0RmlNd202MTE4TE5PSGNOV1hIeU5ZT1I4VXFkcEZibmRHNApYVXlHamxzRjJmTVdDSXBvd21rL1FDa3M3REdRdHB6OHp6djJRSkZqcXdLQmdRRGhsRTJkQUNyUWpGT0ZrcjNlClQ1WHFxbWhDVkVoS3hTMGREejRxSm5FdWtnejFnTXMwa05Bd2VHeEhDZWxGY0FTbGFRMERKOXd5bkY0TG1SdFYKQTBCcjRtQTlwWjlDbWhLTTgyTXVZTEhzWXFwT1cybDBYR1hObUtSckwwVnVRMWtyaHhDekFSVFU0MlNZTWN1bApwU3FoN251YnFnRDFQT3BPTHBmbHpvTjJyd0tCZ1FETjJwK0s2Y1lacWY5ZlJFem4vTUlWVWV0ZHdLNnY3OVNCCkZHdGFsS1J5WHE1Zit0VWZRUk9QNy9kN3dqSFAyMklYTURNeXdzWFU4ZGZtY2Zha2l5aDVpdlpLcUc5Z0tqLzEKQnRHS1NIK240ejJCcU5ra2lzc2l2WUdpWVA4UUR6cFFueUNOT2dJbjY1VVRaSkE3Z2c2Y3hjaWZUY01KSCtSegp1WjVoQWx3aFh3S0JnUUNmcEFDNVYyRDFiaG05c2ZmRTJMWFQrUDBIMC9YRlZIMTB6MURESzZsMXQ4NkwvN1hQCllaeTBjTVRRRVdlUXlKSEJMZk1UaEtZRSt6eGpJTnVDOG1ZbzgzQUFzTEZneFFEVDEzc2RXemtQZlZQaFdEZnQKTFdhdWRaUUdkdEhBRXRHTVNHMjlBTXJwVG5QbWNYY1pweVhncTVHMnZEMHBVUTdRZlpEcUJaaHI2UUtCZ1FDSApjUURuOVVoU09uZTd4c1NUSHNyVUhFSXdQVWF5bTZuR0JCbGVUODZqTVlpcHZlL2IwSVYrZnZUbWlLOGRnOHJXClZ2Qll4YTVFblpyZ0ZMdWpKNnhKekJTZ3FwSWRRNjh4R0h0bDhLMk5XUVp1K1JsbDRhd2wvMm43M0xYMWF3K0QKWEMrZXZEd082QUg5OEh5MXFxelNtWStXd1NOQ0xhbXlPcjdxTlJOSklRS0JnSFdKa1NKakMvYTBOZzFocThRdwpXRWlPTFRCclV3QitJbjdaYng5aVhxcUFZYVdmYXFGRWVKRkRwYzF1VjdVRXZrU0l4VjRhSnBBbnY2cy9xeGxuCis1U1Z1bkplMjZsV3FWV1VKakk3Z3UxLzkyVFd6V2QzWTJsTWw5NFZKeWNBS1VoZjBhQUtybURXV2xRVXNPRDAKcHFveXVUVjRRMWVEckxZOUNCL0UzcStQCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K\",\n \"rsa-protected.pem\": \"LS0tLS1CRUdJTiBFTkNSWVBURUQgUFJJVkFURSBLRVktLS0tLQpNSUlGTFRCWEJna3Foa2lHOXcwQkJRMHdTakFwQmdrcWhraUc5dzBCQlF3d0hBUUlaMDIxWnQ1Qk5Jb0NBZ2dBCk1Bd0dDQ3FHU0liM0RRSUpCUUF3SFFZSllJWklBV1VEQkFFcUJCQWdYRG1JNTdXVDB6WENvK0V2K0UyZEJJSUUKMEhSQlhqclFscS95TVBEdWM4UmJ3YmpuTzZLUElEUVF6ZmRCOEV2VVo5Ynd0QzJ3YWxocGdzcmlRb1pEajVtbwpUczZXSEI3T1ZnYkZIdnJiZlB5cm56eUU1OHZxRVJQL3VreU9ueTlsQXlrU3Y2TWhpeHMzMENYQW9LaFByM3B4CnBCV3dmU1lFcFEvSDdlSHoyUGkwYWNzVEh4V2FQT2VkdGRzbDYxbERaSXFBTExlTzgwS3JPdTg5TU9zN05hRWwKK0V4aVN6L0hjNHRzQjBMai9OTDVnNDNqcjhYbXJYK0ZGYUJ4UERHQzVZRFRmWmlJUFFxQVdqcGJkcjBiZ0xXcQo4ZmZKM2JYdEpHeENoZjNlemZ0V0FKb3lDUjA1SWpRU3lpaWNNYlprY1U0cjR1SU4yVmsrbUJXRDVYYVkwWFdNClhxT3RoWGJ5ZXNXNEI3a2loenRQc2pCM2thRVdMekhVaTA0NFplMnRUbVlONFZBSkFvYkZxVlZkNThpcWlSNHMKcWpwU3VjMXRPMzJMMjNwODdKRzZweUFZcStCNTFpZFhhTFlUOVhrNUZnNVp1RFhxZjdLV0dVelowUnFoR1FCRgpOY2R0dEM4U0dtdXpCdlNKZ3dLbk9NY3BrRUN0aXJtMzdJZXlJb090SWZwc3Z3akxUa2dvbG5Uc01FQ3RSRjNCCjJmcDVLVlJvUmx5NnpRUUUwOFkwWlNZaWxjL2tYc0c2eEdWcGFob051TkVZSGw0b1NKcjdnVkJUNUJnYkN3eDYKSXNHT0gzSUM2THFHeldDYkk4blpjRDJValV1blU3MzlmUzhPSHl5YnppMnRWUHR6Wjk5RDRKMWNKMU9qZk50dQp5NXlGYzJaMmJVK1hKVUJ6WGVPa1hQMUZTQ2REN2Z2ekdnSHFYSU02RG5TRVNaUklQN3BoVjdwVEpjMllUR2toCjBwNXJZVkRzZk1GRGFUdnJIS0lFK3d1RG9GaUJPU0pVdVJUNFFFdlhwSzNiOFpUSHduenJ6QnVYU1ZlZEhELzUKSHhhR3lkSy96R003SXJZd0ZkNnFDeFZTQU5nakJsZUtTQ1dSRXNqK2xZZnpteS81MXZURXRRZVU5WXBIKzBaaApnb0l5VlhFSk9UQ0NBQXE0NkdkVEJnUlJqQzdMeE5IUzBlWU40SjQzVWVPemhLYWJYdFRPQlEvMXVXVndhTThEClo5ekJZTHJ1QmsvYkE2WmhYNU9BcXlBeEs5Mnl1SGdlQi8rNi9pMU92R211Uk5BNjFDczY2bnNmTzlZd1RPMFAKZGtSaTRzYUNrNmpRNmgrVkN3TVlPMm1MZ3l6eTBMaC8yVFdRMXRoMkZnU2o3WHlMV0puWWhUY3MxVXpuN3RlUgpqWlFzbjFZUTZaWERjRWZ4S09KbWk3ZHdaK0FydHMwaWFKL05XbXRwNjZKVzcrR3crYzQxYTZMQVptWVpwaHFCCm1tUCthQTRFa1VoNDJneW1vTEpTR255c3ZmNTFUMEdvaEErQzlSZFQ2Z1hqYlhVN3hBMzRLUWFocmo1VHhUN3kKVXJodHdPamc5MWtQU3RNYVJVZ3lTQTJzUVMzeFordG8yQlhaVFBhU0Z5T1V3ZlFRSnArb1NGK2Rya205Y256cwpyUVdIV2RLMXJQaGpxbU54a01OYjBlcS9XUWpueFRxZ2lMckNlWjB6N3RTYzh0dlYvQS9ISW81TGwreWhMRUd4Cmd6Nk9jZUJ5akZuTUxzUmYvNk8zRTgvVm5JY0cwL2Z6aFlJM0V1ekY5U2JFTUtvN3hKQzdNZmdrdjJmSjQzLzMKQ3BhWHVlaTZLZER1ZmJkTVVGc2JSc2dmMHQ1dTNGQnlzM0psMExxT2daelhXZDhBUFp2clFnTnJmUlFDTlA1QwpvdElqdVo5ZTNYajIyK0E0YUJVdUttN2RoQjFNR0JGQmFLS0R6UnJxM3ZOL2ZjRXJHSDVDVVJ2a2o5N3gxbVo1Cnl6SDhtYVdsMmUrU0xZMk5WUXU2aXBmUVNMQTZlaGduSE9mTXp3dzlxdXVSK1hyQm9aSXJ1NUw3UlorNlJ2ODAKWnhwMGUrTWU5aUlFZDNtWTgreCtnbEREdytVRHE4eEZHWE9pUVZ6YUhvUDdTamVZTTVXeHNyNm1TVjJoeFVlZwpBRmNxYjVEaHJEbmM4UmlybFpqRjQ4M0x5cmkzS1hySjUycFBxT0tpRGkvcQotLS0tLUVORCBFTkNSWVBURUQgUFJJVkFURSBLRVktLS0tLQo=\",\n \"rsa.p12\": \"MIIJ8gIBAzCCCawGCSqGSIb3DQEHAaCCCZ0EggmZMIIJlTCCA/IGCSqGSIb3DQEHBqCCA+MwggPfAgEAMIID2AYJKoZIhvcNAQcBMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAizNDzk7E+b5AICTiAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEI/t1VtVBH5X7VtWA99KbKuAggNwVeA4h3kl2WhhP63YcR5qCBaJquqSDA8er5Bpv+zcwodxPfxpVLmcg9VS60g+eTOKbk0qRzJzQqb/bSEW23XS4fX6ulkdaIRTJVlhyhXqdwIRnzVjJooWCnmdsQhYxRmUeC2JW9hY7FLP5XQOERYoQd0HyrBBWWeiIQTutqGHO2AFN7f7/o3N/ZG1fgA3xnb1biQYJ0o8a2qNyaqVsJg6/4UNgQ8TC5aA7SK4gddfn/aiCmsJ7zciapPlOWftwVO0tUfXqPbDIqRK0vPuJz8ngRPldDg56IyVwCpf+p3osC5EBjthBIB2KKE+9R0CIZ1tn3jGGrsg85VhJhtRWg9BVc7sJtZ/bntz9fpPQuAGJRszqk1K7uXihi9GW53K4FROl08K1HrDYKpYhQPbrRGn96fy6pfKwiGatkestZZwRaa8vwiQ5wdx/38KHhxf8Kjdix9MY/ysVMswVQzIsnXVKpHxEo0811+ut4eKbZ9hOdGEZGqQpIIJSk1Z000oH2FT5onrN35ezyZLe1GfEhhgYcazZS+rhWCAsE+0sLJDuUCcnDT3dExzGpIQqjP8WsoUi5S5DrgapbJcMJO98tEeb8W5gCcdkMNoL3L7jQH0DqTX4bOr+cIJxp2HiOLr5noJ7BZmmcn4vJ1kvzE7LyQtbXs/BMQh2hOzVqy4/XWsHUprxmycA6vDaU/OYvSDurJ23dqR9asQefXLQiPzKsIXocX3J9R28hvY5h/tqaf5b6PzHd2ABYViuqkPbohAYMHua+ghJvY4DH66LIgkWVBTGqmudmvITpQ/gxDFpqlPF2anpF2on01VcgxioaOKZphUvtnrQopscm4dHBzF+BWaYqxzuamW0Dg8iupbRODVQchOfH9UavIwzjjDudGyfeOHqt6T1aAbISxZJ5A0cWE29sq3MdKpS++5jkSPDaM8K3baApKBn0FRPW9CdMt0DqEwmUqeVUf9fW2ucaLXrC1iigbaHLEgxmkU9QhtixaJ3iSPZ677Kq5SyP8se/w3nb1V640U8aP4maV5WomHC5CEuilW0nK7Ah81gYjOzuB73xW40+o2P9muwNTkLjR96559f7qUKEEwqbqW2Snh+ARTyrxdKM4EWn1utIlGZkwyVpvixKZyx6X3uCJWxkG8CgSyxfpeVASO1i40BMb10iizpzCCBZsGCSqGSIb3DQEHAaCCBYwEggWIMIIFhDCCBYAGCyqGSIb3DQEMCgECoIIFMTCCBS0wVwYJKoZIhvcNAQUNMEowKQYJKoZIhvcNAQUMMBwECBY9LMHsobnnAgJOIDAMBggqhkiG9w0CCQUAMB0GCWCGSAFlAwQBKgQQm4o6ofvMjHyl8QYRH3XPzgSCBNCrqTVhxZNF+ecVG/phALUczcLeltze8fZLbuPqKTxZELzkAnFAWXaAERAZxWSxXmIG2vEr7HDu2VY5lyQf/ni17bkc5u0T6mc8PRf582b8ezCxN+ETLEmGk3RGtg8JLAmhiZPRBLPvgI5iyVn4JAHA3tm2eCArFUr89CFZdRX2AonLRreof+dn2alqIUikPGFffEvCbwp8Db7TuUmJRYglYFPt3PzzLIrgXDfoHC3kXqMkuLPX/Z6bZAsuGzWOI7Wk3f7fzE8gdz2knEPzDX9JRXEwMnZrCMcoeCvB9JdYjk8Nx7U9O73GTGgPzQAl3Gu1fcMEUuw7quuDfN8Px4oRLfinyqyfGuo2E1SvHwHNcnZq5do1i6sm5DnBcbQ7g53L9kyKwW70jcT64rPVyPEYhbd1KfcOxr/DMvx/POqaqtQ1jcixGeab48mtiMrG2PzXsOqbQTAsXOx3LsTC0/lgzy2n7nJZ2o2MZ+UDSw8P1TDnYOkQAbB1AgOqXneuihyPNtMbR5usA7cTTGYmL61xaRyBIlOk4rOKczLqOuPs/TuAJk4EUnQLYm5zEOCAVkBO+tPdx9aVB/Bv46LsEGj+I07TKQh/jEd4C9r8FCBpCXMsBzzGgCwcFAJqpFEQJiSiuvWH4fZzrpO6CuttefFm6Eck2RhcMb/lO3Sfb7jbJePHwK1vca+1dYkxTq7k5ITmWcIj4Qzs1rryg1ZSOGW5RmQ21xiw1j+KIN8+9xm5KwFKKrILrMHZnmkrACFIMP0bbRrLTMcEbMfLQKvZUpyYDAdu35NlAai6sqrGbHntTmad6dPGnRblisJaW7L+rLYmex79Z1yzIa5IKHNSkbELrLYjji2+NN0PfWUnq/c8dc5z012iqfYMfhAsueMlN3Hkfu3Wz1PvcMyHZZvdZaTTWu6NnL2gQXZAelLOUDkbP5xDLCTotbOgz9FJWp3zs48cERgmQu4lRXjLacZeeiHHyQur+NhndQliTgTEx4aJjt2RJgeaN810yeqGyB8QSrIAp7q0VVq5fsV2jtrdrhczIL2D+6b8w4sBISMmjNL172YuyJtW48kx4YUnkObTYYopbzfznJYTLEgtV9APwTloh9hStc/ehHBqoR6Vpry9mCjLKZQx2OUaf4Og2n4WnfcPFd9QTAyyfexnUBOq7uzt3PyjWdhD6xkZEyIWcAFS1Pzv8N0fQl8h5/IczJ8RRbXfRSNdJFLWL/0xRd4G7EtZV+P9V/3P4sJWfaE1fTe/fNRmF7Ey1g8bY11bDaWvDRw4mDuX2AEzZLvLUdRCzz65y7x1xu14X/phTqH2yvDYZF+flBGW4fA8nPbRoT+9YanZp/SBNTmauLc2c+p971NCdhdXVhzA7l+hCKIHy9xDuIsi6cF0+/v3lZEcz9kiwzj635kOn3opaaXdRPLGWnboDPftE2LasSlzLsCkQw57mokUYHWuPObEjN5i8zRxzZ2zSxjlXVuhR0izyyBH8RuVpispf3kfEmz+vlR8/Cd9TWO0zBob05wQE0H3q1PUAZ/pY3N1n+nb8Z1+qGmONErCfyWxaRDQkw8FXdzNRPp7oXWv/faMbVspf9nxj+y3pXwP/34p7Dt+ETjbl+8iz+CQBdr55LPjsJ0CWwquFtpw2TE8MBUGCSqGSIb3DQEJFDEIHgYAcgBzAGEwIwYJKoZIhvcNAQkVMRYEFLJrXd1A52LF9xNzjm/IJ2vC7x9JMD0wMTANBglghkgBZQMEAgEFAAQg/UmftAyRiC5O4ysmNnS/YuI7DywCg2DnQsjO7LlhCE0ECF884bi6IU+7\",\n \"rsa.pem\": \"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5ekNDQWQrZ0F3SUJBZ0lVYi9uZ2NidDBlcmZQc1BVOGlKSlBoWTM1M0pvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1dZbXhwYm1SbWIyeGtMbVY0WVcxd2JHVXVkR1Z6ZERBZ0Z3MHlNREF4TURFdwpNREF3TURCYUdBOHlNRGs1TURFd01UQXdNREF3TUZvd0lURWZNQjBHQTFVRUF3d1dZbXhwYm1SbWIyeGtMbVY0CllXMXdiR1V1ZEdWemREQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUxWa1p3WlUKK1ZFbjJSUC80NldHbmpvclBxZURkL0xiQTM4LzI1WWNHVmEvTEVvc09sQlF3MzR5SXg4MHFLOG4xKzRQSUhHWApMckNWZVhSczB0ZjQxQm9IRyswaVNXM2pSMVR0NEQxNXdyVGNkMCtPTUY4V1REbUQ0a0krNlJ6QzBKemtHUHY4CnJpUEVNOHk4WFNrUzdzU2hKYzZkbnExKzFIRm5aUzhPSTJGay9BN2RCcEhrTWMrMVEraUlpMithOGZtL1pWNVkKMDJxTndkVm1hVHRsdUlwa0lsY3Bpa0FyalBtYlk3RWhIVDZXbFhIeXdtWnNvL2tydzYzbW9MUUlZUys1SGtvSgprZEpZNzNYUmNXWmtiZ3UrVk9LbEJYUkFzcG1icERPN3dwSVZydmRWVzRKaUk3SCtLOFlxb09iUG5ZUS85aGxrCmh0aXJLNWsyWVpuNW1mRUNBd0VBQWFNbE1DTXdJUVlEVlIwUkJCb3dHSUlXWW14cGJtUm1iMnhrTG1WNFlXMXcKYkdVdWRHVnpkREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBaXQ5Q25GUk5tYVFvSDEzNWs3ZURwb1QyWjhMMgp6MU5MTXRLM25FSFIvVHRvTTJmRVErOUF6UVg1RWQ3STZBNmN4MnJ4VkhoQWxqRjJIMlNWTEJGazZMQmM2cW45CjI4aDVLNTRDUlErSnFIb2d3dUhMWnlkeU1uQk1TWnp1VS9Va09NcFRSVThnR3VRbEMwZEVkbitlYW5wRzY3amEKQ1BHYkxWclBONFZOZ0IrWVdoR1ZoUWRNWFRrd2QybUI3Y1h6U05rVXg5OFQxcTBEcG1YaFdqekkrU203cVJURAp4cC9uMGJGaGh5dm5zVkx6VlY4eStXY3B5dk40cm9qQ2tURGtkbnJheE8wZUdDcy96ZWI2bWY2UzE0dkE2aUN1CkVlbnAxUlJ6Rlcwd2ZkVkxwb3QwcEd6RzVXYWpOU0x6M01ZYUNYbWpYSjBrbUcwYTAyTVRWVnZxdVE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==\",\n \"wrong-chain.pem\": \"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5ekNDQWQrZ0F3SUJBZ0lVYi9uZ2NidDBlcmZQc1BVOGlKSlBoWTM1M0pvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1dZbXhwYm1SbWIyeGtMbVY0WVcxd2JHVXVkR1Z6ZERBZ0Z3MHlNREF4TURFdwpNREF3TURCYUdBOHlNRGs1TURFd01UQXdNREF3TUZvd0lURWZNQjBHQTFVRUF3d1dZbXhwYm1SbWIyeGtMbVY0CllXMXdiR1V1ZEdWemREQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUxWa1p3WlUKK1ZFbjJSUC80NldHbmpvclBxZURkL0xiQTM4LzI1WWNHVmEvTEVvc09sQlF3MzR5SXg4MHFLOG4xKzRQSUhHWApMckNWZVhSczB0ZjQxQm9IRyswaVNXM2pSMVR0NEQxNXdyVGNkMCtPTUY4V1REbUQ0a0krNlJ6QzBKemtHUHY4CnJpUEVNOHk4WFNrUzdzU2hKYzZkbnExKzFIRm5aUzhPSTJGay9BN2RCcEhrTWMrMVEraUlpMithOGZtL1pWNVkKMDJxTndkVm1hVHRsdUlwa0lsY3Bpa0FyalBtYlk3RWhIVDZXbFhIeXdtWnNvL2tydzYzbW9MUUlZUys1SGtvSgprZEpZNzNYUmNXWmtiZ3UrVk9LbEJYUkFzcG1icERPN3dwSVZydmRWVzRKaUk3SCtLOFlxb09iUG5ZUS85aGxrCmh0aXJLNWsyWVpuNW1mRUNBd0VBQWFNbE1DTXdJUVlEVlIwUkJCb3dHSUlXWW14cGJtUm1iMnhrTG1WNFlXMXcKYkdVdWRHVnpkREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBaXQ5Q25GUk5tYVFvSDEzNWs3ZURwb1QyWjhMMgp6MU5MTXRLM25FSFIvVHRvTTJmRVErOUF6UVg1RWQ3STZBNmN4MnJ4VkhoQWxqRjJIMlNWTEJGazZMQmM2cW45CjI4aDVLNTRDUlErSnFIb2d3dUhMWnlkeU1uQk1TWnp1VS9Va09NcFRSVThnR3VRbEMwZEVkbitlYW5wRzY3amEKQ1BHYkxWclBONFZOZ0IrWVdoR1ZoUWRNWFRrd2QybUI3Y1h6U05rVXg5OFQxcTBEcG1YaFdqekkrU203cVJURAp4cC9uMGJGaGh5dm5zVkx6VlY4eStXY3B5dk40cm9qQ2tURGtkbnJheE8wZUdDcy96ZWI2bWY2UzE0dkE2aUN1CkVlbnAxUlJ6Rlcwd2ZkVkxwb3QwcEd6RzVXYWpOU0x6M01ZYUNYbWpYSjBrbUcwYTAyTVRWVnZxdVE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlCYWpDQ0FSR2dBd0lCQWdJVVFha3pKU1BMZVVVVkxEUGFzeXkrSDdjU2IxOHdDZ1lJS29aSXpqMEVBd0l3CklURWZNQjBHQTFVRUF3d1dZbXhwYm1SbWIyeGtMbVY0WVcxd2JHVXVkR1Z6ZERBZ0Z3MHlNREF4TURFd01EQXcKTURCYUdBOHlNRGs1TURFd01UQXdNREF3TUZvd0lURWZNQjBHQTFVRUF3d1dZbXhwYm1SbWIyeGtMbVY0WVcxdwpiR1V1ZEdWemREQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJIODdzcXZybGppRkhUUXlOTG16Ck5Jd3gzNDM1czg3OHRLd1hjVVlxRU9GdUxDL25Fb0JmTWE2K1UwTnQvQ0ZnVzhNV1QrV3ZjU1VqTjh5cFNnY3cKS0U2akpUQWpNQ0VHQTFVZEVRUWFNQmlDRm1Kc2FXNWtabTlzWkM1bGVHRnRjR3hsTG5SbGMzUXdDZ1lJS29aSQp6ajBFQXdJRFJ3QXdSQUlnUFdmSmhxVm1ZeTZURjN5M0pmbUZDSHFnN1NWbVR0dWR2K2RteDc5enBwTUNJQ2VWCkoxUnJTRjZELzhjVE1XZ2xkbWtuQ05lTDlJb3V6ZWVLb1E2WG10aFYKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=\"\n}\n","spec/conformance.json":"{\n \"version\": 1,\n \"protocol\": [\n \"independent-go-rust-reference-recovery\",\n \"randomized-output\",\n \"tamper-failure\",\n \"wrong-policy-failure\",\n \"uint64-policy-boundary\",\n \"complete-exponent\",\n \"inclusive-size-limits\"\n ],\n \"normalization\": [\n \"pem-whitespace\",\n \"pem-pkcs1-pkcs8\",\n \"protected-pkcs8\",\n \"modern-p12\",\n \"exactly-one-p12-key\",\n \"key-pair-match\",\n \"leaf-first-chain\",\n \"chain-signatures\",\n \"validity\",\n \"rsa-2048-8192\",\n \"ec-p256-p384\"\n ],\n \"lifecycle\": [\n \"initial\",\n \"empty-plan\",\n \"restart\",\n \"metadata-edit\",\n \"renewal\",\n \"context-rotation\",\n \"inline-reorder\",\n \"saved-plan-change\",\n \"write-only-version\",\n \"import\",\n \"drift\",\n \"deletion\",\n \"conflict\",\n \"uncertain-write\",\n \"missing-provenance\",\n \"algorithm-cutover\"\n ],\n \"qualification\": [\n \"secret-absence\",\n \"independent-install\",\n \"two-way-ciphertext-handoff\",\n \"all-inline-nodes\",\n \"linux-macos\",\n \"live-status-valid\",\n \"strict-trust-hostname\",\n \"served-fingerprint\",\n \"https-success\",\n \"renewal-propagation\",\n \"cleanup\"\n ]\n}\n","spec/v1.md":"# Native Blindfold contract, version 1\n\nAll binary lengths are unsigned 32-bit big-endian. Integers are unsigned big-endian. The envelope\ncontains, in order: length-prefixed UTF-8 canonical tenant ID; uint32 key version; uint64 policy ID;\nalgorithm byte 2; length-prefixed minimally encoded complete public exponent; length-prefixed\nminimally encoded modulus; length-prefixed modulus-width wrapped block; AES-256-GCM ciphertext\nfollowed by its 16-byte tag. The textual location is `string:///` followed by standard padded base64.\n\nFor policy ID `p` and exponent `e`, the effective exponent is `e * (2*p + 2^31 + 1)` without machine\ninteger truncation. Generate a random block of modulus byte width minus two. Set bytes 0 through 3\nto `de ad be ef`. Bytes 4 through 15 are the GCM nonce and bytes 16 through 47 are the AES key. The\nremaining bytes stay random. Wrap the unsigned block by modular exponentiation with the effective\nexponent and modulus. Use empty GCM additional authenticated data. Encryption is randomized.\n\nInputs and public documents have a 2 MiB inclusive limit. Final encoded certificate and encrypted\nlocations, including their prefix, have a 131072-byte inclusive limit. Public RSA material must have\nan odd 2048-8192-bit modulus, odd exponent greater than one and smaller than the modulus, and a\nnonzero uint32 key version. Policy ID is a canonical decimal string within uint64. Public documents\nmust have one `data` object, equal canonical tenant IDs, no duplicate keys, aliases, merge keys,\nmultiple documents, float coercion, or conflicting root fields. Known camelCase names normalize to\nsnake_case; supplying both spellings is rejected. Base64 must be canonical.\n\nAccept RSA 2048-8192 and EC P-256/P-384 private keys. Normalize keys to unencrypted PKCS#8 PEM.\nProtected PKCS#8 and modern P12 are native inputs; P12 must contain exactly one private key. Reject\nmixed sources, unmatched pairs, duplicate or unrelated certificates, invalid chain signatures, and\nexpired or future certificates. Locate the matching leaf and order supplied certificates leaf to\nissuer using issuer names and signature verification. Serialize PEM with 64-column base64 and LF\nline endings. A chain may omit its trust root. Check a supplied self-signed root signature.\n\nPublic identity fields are lowercase SHA256 hex: leaf DER fingerprint, SPKI DER identity, and\nnormalized chain PEM identity. Expiration uses UTC RFC3339. Context digest is SHA256 over canonical\nJSON of the array `[public_document, policy_document]`, with recursively sorted object keys, known\naliases normalized, arrays in document order, and exact integer tokens. Preserve every public\npolicy field in that digest so a policy change rotates encryption.\n\nThe reserved `f5-sales-demo.com/blindfold` annotation is a JSON string of:\n\n```json\n{\"version\":1,\"entries\":{\"default\":{\"chain\":\"sha256\",\"spki\":\"sha256\",\"context\":\"sha256\",\"ciphertext\":\"sha256\",\"algorithm\":\"RSA\"}}}\n```\n\nInline IDs must be explicit and unique within the resource. A named certificate defaults to\n`default`. Ciphertext hash covers the exact UTF-8 encrypted location. Never record plaintext keys,\nbundle bytes, passwords, or a private-key hash. Provenance is reconciliation metadata, not\nattestation. Reuse only when its public identities and context match the requested normalized\ninputs, and its chain and ciphertext hash match the actual remote material. Missing or malformed\nprovenance regenerates ciphertext. Reject an in-place RSA/EC algorithm change; require a new\ncertificate/reference cutover. Preserve unrelated metadata and resource options.\n\nTerraform prepares available inputs during planning and encrypts only during apply. Write-only key\nand bundle inputs require `material_version`; secret values never enter state or private state.\nPersist public plan identities and reject changed normalized file material or refreshed context\nwhen applying a saved plan. Refresh context during normal planning; changed context rotates once.\nUnchanged inputs preserve ciphertext across process restart and sequential tool handoff. Import\ndoes not recover private inputs. Observe remote private-key fields and repair drift. Carry the\nserver resource version into one mutation attempt; never retry conflicts. Reconcile accepted or\nuncertain results by named readback. Concurrent ownership is unsupported.\n\nManifest ensure uses a top-level `x-xcsh-blindfold` object with `version: 1` and `certificates`, an\narray of entries containing `id`, `pointer`, `certificate_file` and `private_key_file` or\n`pkcs12_file`, optional `passphrase_env`, and `policy`. JSON pointers point to recognized certificate\nnodes beneath `/spec`; reject unresolved, duplicate, or unsupported pointers. Remove the extension\nbefore API serialization. Private values never enter assistant arguments or reports.\n"},"version":1}
|
|
@@ -25,22 +25,11 @@ function canonicalize(value: unknown): unknown {
|
|
|
25
25
|
for (const [key, item] of Object.entries(value)) {
|
|
26
26
|
const name = aliases[key] ?? key;
|
|
27
27
|
const normalized = canonicalize(item);
|
|
28
|
-
if (entries.has(name)
|
|
29
|
-
throw new Error("Conflicting Blindfold field aliases");
|
|
28
|
+
if (entries.has(name)) throw new Error("Conflicting Blindfold field aliases");
|
|
30
29
|
entries.set(name, normalized);
|
|
31
30
|
}
|
|
32
31
|
return Object.fromEntries(entries);
|
|
33
32
|
}
|
|
34
|
-
function equal(a: unknown, b: unknown): boolean {
|
|
35
|
-
if (Object.is(a, b)) return true;
|
|
36
|
-
if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((v, i) => equal(v, b[i]));
|
|
37
|
-
if (object(a) && object(b))
|
|
38
|
-
return (
|
|
39
|
-
Object.keys(a).length === Object.keys(b).length &&
|
|
40
|
-
Object.keys(a).every(k => Object.hasOwn(b, k) && equal(a[k], b[k]))
|
|
41
|
-
);
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
33
|
/** Preserve public information for retrieval; only explicitly known aliases change spelling. */
|
|
45
34
|
export function canonicalBlindfoldDocument(value: unknown, kind: "public-key" | "policy") {
|
|
46
35
|
const material = canonicalize(value);
|