Skip to content

Commit 7a7d6ce

Browse files
sorccuclaude
andcommitted
fix(cli): key SSL property whitelists by their property unions
The runtime whitelists in ssl-assertion-validation.ts were typed Record<string, PropertyRule>, so nothing tied them to the property unions in ssl-assertion.ts that they mirror. A union member added without a matching rule compiled clean and autocompleted, then failed at the user's checkly deploy with "unknown property". Key them by the unions instead, matching traceroute-assertion-validation.ts and this file's own source-level rule. A missing or misspelled entry is now a compile error. The unions are exported to make that possible, which also lets users name them when building typed wrappers, as the traceroute analogue already allows. They are prefixed Ssl- to suit the flat public export namespace, following the IcmpLatencyProperty / TracerouteResponseTimeProperty convention; both names are new to the public API, so nothing breaks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 789b7d1 commit 7a7d6ce

3 files changed

Lines changed: 17 additions & 13 deletions

File tree

packages/cli/src/constructs/__tests__/ssl-assertion.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ describe('SslAssertionBuilder', () => {
134134
})
135135

136136
it('rejects unknown property names', () => {
137-
// @ts-expect-error 'bogusProperty' is not a CertificateProperty
137+
// @ts-expect-error 'bogusProperty' is not an SslCertificateProperty
138138
SslAssertionBuilder.certificate('bogusProperty')
139-
// @ts-expect-error 'bogusProperty' is not a ConnectionProperty
139+
// @ts-expect-error 'bogusProperty' is not an SslConnectionProperty
140140
SslAssertionBuilder.connection('bogusProperty')
141141
})
142142

packages/cli/src/constructs/ssl-assertion-validation.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Diagnostics } from './diagnostics.js'
22
import { addAssertionDiagnostic, quotedKeys } from './internal/assertion-validation.js'
3-
import { SslAssertion } from './ssl-assertion.js'
3+
import { SslAssertion, SslCertificateProperty, SslConnectionProperty } from './ssl-assertion.js'
44

55
// The comparisons the backend accepts per value type. The `>=` operator and the regex
66
// operator are both dropped for SSL, so neither appears in any set.
@@ -34,7 +34,10 @@ type SslSourceRule =
3434
| { properties: Record<string, PropertyRule> }
3535
| { comparisons: Comparisons }
3636

37-
const certificateProperties: Record<string, PropertyRule> = {
37+
// Runtime counterparts of unions that exist only at compile time. Typing them as a
38+
// Record keyed by the union makes a missing or misspelled entry a compile-time error,
39+
// so neither list can drift from the union it mirrors.
40+
const certificateProperties: Record<SslCertificateProperty, PropertyRule> = {
3841
daysUntilExpiry: { comparisons: NUMBER },
3942
keySizeBits: { comparisons: NUMBER },
4043
subjectCN: { comparisons: STRING },
@@ -49,7 +52,7 @@ const certificateProperties: Record<string, PropertyRule> = {
4952
isCA: { comparisons: BOOLEAN, booleanTarget: true },
5053
}
5154

52-
const connectionProperties: Record<string, PropertyRule> = {
55+
const connectionProperties: Record<SslConnectionProperty, PropertyRule> = {
5356
tlsVersion: { comparisons: VERSION },
5457
cipherSuite: { comparisons: STRING },
5558
hostnameVerified: { comparisons: BOOLEAN, booleanTarget: true },

packages/cli/src/constructs/ssl-assertion.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,10 @@ export type SslAssertion = CoreAssertion<SslAssertionSource>
106106

107107
// The certificate/connection property names the backend understands. Narrowing the
108108
// `property` parameter to these unions turns a typo into a compile error and drives
109-
// autocomplete. The runtime whitelist in ssl-assertion-validation.ts is the source of
110-
// truth for object-literal assertions that bypass the builder.
111-
type CertificateProperty =
109+
// autocomplete. Object-literal assertions bypass the builder and are checked at deploy
110+
// time against the runtime whitelists in ssl-assertion-validation.ts, which are keyed
111+
// by these unions — so adding a member here without a matching rule fails to compile.
112+
export type SslCertificateProperty =
112113
| 'daysUntilExpiry'
113114
| 'subjectCN'
114115
| 'issuerCN'
@@ -122,7 +123,7 @@ type CertificateProperty =
122123
| 'selfSigned'
123124
| 'isCA'
124125

125-
type ConnectionProperty =
126+
export type SslConnectionProperty =
126127
| 'tlsVersion'
127128
| 'cipherSuite'
128129
| 'hostnameVerified'
@@ -165,8 +166,8 @@ export class SslAssertionBuilder {
165166
* `'issuerCN'`, `'signatureAlgorithm'`, `'sans'`, `'selfSigned'`).
166167
*/
167168
static certificate (property: 'signatureAlgorithm'): GeneralAssertionBuilder<SslAssertionSource, SignatureAlgorithmValue>
168-
static certificate (property: CertificateProperty): GeneralAssertionBuilder<SslAssertionSource>
169-
static certificate (property: CertificateProperty) {
169+
static certificate (property: SslCertificateProperty): GeneralAssertionBuilder<SslAssertionSource>
170+
static certificate (property: SslCertificateProperty) {
170171
return new GeneralAssertionBuilder<SslAssertionSource>('CERTIFICATE', property)
171172
}
172173

@@ -176,8 +177,8 @@ export class SslAssertionBuilder {
176177
* `'cipherSuite'`, `'hostnameVerified'`, `'ocspStatus'`, `'resolvedIp'`).
177178
*/
178179
static connection (property: 'tlsVersion'): GeneralAssertionBuilder<SslAssertionSource, TlsVersionValue>
179-
static connection (property: ConnectionProperty): GeneralAssertionBuilder<SslAssertionSource>
180-
static connection (property: ConnectionProperty) {
180+
static connection (property: SslConnectionProperty): GeneralAssertionBuilder<SslAssertionSource>
181+
static connection (property: SslConnectionProperty) {
181182
return new GeneralAssertionBuilder<SslAssertionSource>('CONNECTION', property)
182183
}
183184

0 commit comments

Comments
 (0)