@@ -2,7 +2,12 @@ import { Injectable } from '@nestjs/common';
22import { existsSync , readFileSync } from 'node:fs' ;
33import { join } from 'node:path' ;
44
5- export type TemplateValidationStatus = 'live-verified' | 'needs-fix' | 'needs-review' | 'unknown' ;
5+ export type TemplateValidationStatus =
6+ | 'live-verified'
7+ | 'requires-secrets'
8+ | 'needs-fix'
9+ | 'needs-review'
10+ | 'unknown' ;
611
712export interface TemplateValidationSummary {
813 status : TemplateValidationStatus ;
@@ -27,9 +32,18 @@ interface TemplateValidationLedger {
2732 entries ?: Record < string , TemplateValidationLedgerEntry > ;
2833}
2934
35+ interface TemplateRequiredSecretTarget {
36+ name ?: string | null ;
37+ type ?: string | null ;
38+ description ?: string | null ;
39+ placeholder ?: string | null ;
40+ }
41+
3042interface TemplateValidationTarget {
3143 name : string ;
3244 updatedAt ?: Date | string | null ;
45+ requiredSecrets ?: TemplateRequiredSecretTarget [ ] | null ;
46+ manifest ?: { requiredSecrets ?: TemplateRequiredSecretTarget [ ] | null } | null ;
3347}
3448
3549const VALID_RECOMMENDATIONS = new Set ( [ 'keep' , 'fix' , 'consolidate' , 'delete' , 'review' ] ) ;
@@ -40,6 +54,19 @@ export class TemplateValidationLedgerService {
4054 const entry = this . findLedgerEntry ( template . name ) ;
4155
4256 if ( ! entry ) {
57+ const requiredSecretNames = this . getRequiredSecretNames ( template ) ;
58+ if ( requiredSecretNames . length > 0 ) {
59+ return {
60+ status : 'requires-secrets' ,
61+ recommendation : 'review' ,
62+ terminalStatus : null ,
63+ artifactsCount : null ,
64+ verifiedAt : null ,
65+ rationale : `Template is credential-gated and requires live secrets before execution: ${ requiredSecretNames . join ( ', ' ) } .` ,
66+ isCurrent : true ,
67+ } ;
68+ }
69+
4370 return {
4471 status : 'unknown' ,
4572 recommendation : 'unknown' ,
@@ -103,6 +130,18 @@ export class TemplateValidationLedgerService {
103130 return null ;
104131 }
105132
133+ private getRequiredSecretNames ( template : TemplateValidationTarget ) : string [ ] {
134+ const requiredSecrets = Array . isArray ( template . requiredSecrets )
135+ ? template . requiredSecrets
136+ : Array . isArray ( template . manifest ?. requiredSecrets )
137+ ? template . manifest . requiredSecrets
138+ : [ ] ;
139+
140+ return requiredSecrets
141+ . map ( ( secret ) => secret ?. name ?. trim ( ) )
142+ . filter ( ( name ) : name is string => Boolean ( name ) ) ;
143+ }
144+
106145 private normalizeRecommendation ( value : unknown ) : TemplateValidationSummary [ 'recommendation' ] {
107146 const recommendation = String ( value || '' ) . toLowerCase ( ) ;
108147 return VALID_RECOMMENDATIONS . has ( recommendation )
0 commit comments