@saasicat/cli 1.0.0-rc.18 → 1.0.0-rc.19

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/dist/.build-stamp CHANGED
@@ -1 +1 @@
1
- 5800fd6cc355627c7191678dd59fd575d2569a6ae000b10915959a83b34ce7a3
1
+ 6d26748d12c2cc8e839f2a13b89df38079e8253fb11933454d69ef20cc6de850
package/dist/index.cjs CHANGED
@@ -51,6 +51,7 @@ __export(index_exports, {
51
51
  DiscoverySnapshotDoctorCheck: () => DiscoverySnapshotDoctorCheck,
52
52
  DoctorCommands: () => DoctorCommands,
53
53
  DoctorFlow: () => DoctorFlow,
54
+ IssuerIdentityDoctorCheck: () => IssuerIdentityDoctorCheck,
54
55
  LIMIT_FILTER_IMPORTS: () => LIMIT_FILTER_IMPORTS,
55
56
  LIMIT_FILTER_PROVIDER: () => LIMIT_FILTER_PROVIDER,
56
57
  MANIFEST_ACCESS_PORT_TOKEN: () => MANIFEST_ACCESS_PORT_TOKEN,
@@ -1156,11 +1157,85 @@ AdminManifestDoctorCheck = _ts_decorate7([
1156
1157
  typeof import_nest4.AdminManifestService === "undefined" ? Object : import_nest4.AdminManifestService
1157
1158
  ])
1158
1159
  ], AdminManifestDoctorCheck);
1160
+ var IssuerIdentityDoctorCheck = class {
1161
+ static {
1162
+ __name(this, "IssuerIdentityDoctorCheck");
1163
+ }
1164
+ issuer;
1165
+ id = "platform.issuer-identity";
1166
+ label = "Issuer identity against the recorded one";
1167
+ constructor(issuer) {
1168
+ this.issuer = issuer;
1169
+ }
1170
+ async run() {
1171
+ const verdict = await this.issuer.inspect();
1172
+ if (verdict.kind === "refused") {
1173
+ return {
1174
+ severity: "error",
1175
+ message: verdict.refusal,
1176
+ // The number and the identifiers, not the rows: `DoctorReport`
1177
+ // is serialised as JSON, and the dates on a row would come out
1178
+ // as timestamps beside the same dates already written as days in
1179
+ // the message above.
1180
+ // One unknown answered once: `null` for both where the
1181
+ // contracts could not be read, rather than a null count beside
1182
+ // an empty list that reads as "none".
1183
+ details: verdict.running ? {
1184
+ runningContracts: verdict.running.total,
1185
+ named: verdict.running.contracts.map((row) => row.id)
1186
+ } : {
1187
+ runningContracts: null,
1188
+ named: null
1189
+ }
1190
+ };
1191
+ }
1192
+ if (verdict.kind === "not-compared") {
1193
+ return {
1194
+ severity: "warning",
1195
+ message: `The issuer in the file is compared with nothing \u2014 ${verdict.why} \u2014 so a start that names another legal entity than the last one is not refused.`
1196
+ };
1197
+ }
1198
+ const change = verdict.change;
1199
+ switch (change.kind) {
1200
+ case "none-named":
1201
+ return {
1202
+ severity: "ok",
1203
+ message: "No issuer is named, and none was recorded."
1204
+ };
1205
+ case "first-naming":
1206
+ return {
1207
+ severity: "ok",
1208
+ message: `'${change.identity.legalName}' is named for the first time; no contract can name another.`
1209
+ };
1210
+ case "corrected":
1211
+ return {
1212
+ severity: "ok",
1213
+ message: `A correction of '${change.recorded.legalName}' is declared: ${change.reason}. This is what the start found; whether it has been recorded is what \`GET /admin/settings\` shows, and \`issuer.correctionOf\` may be dropped once it does.`
1214
+ };
1215
+ case "unchanged": {
1216
+ const running = await this.issuer.runningContractCount();
1217
+ const weighedAgainst = running === null ? "" : ` ${running} contract(s) are running, and their issuer copies do not follow a change.`;
1218
+ return {
1219
+ severity: "ok",
1220
+ message: `'${change.identity.legalName}' is what the installation recorded.` + weighedAgainst + " Changing the legal name or a tax identifier needs `issuer.correctionOf` beside the values it replaces; the address and the contact details do not."
1221
+ };
1222
+ }
1223
+ }
1224
+ }
1225
+ };
1226
+ IssuerIdentityDoctorCheck = _ts_decorate7([
1227
+ (0, import_common7.Injectable)(),
1228
+ _ts_metadata7("design:type", Function),
1229
+ _ts_metadata7("design:paramtypes", [
1230
+ typeof import_nest4.IssuerIdentityInspector === "undefined" ? Object : import_nest4.IssuerIdentityInspector
1231
+ ])
1232
+ ], IssuerIdentityDoctorCheck);
1159
1233
  var PLATFORM_DOCTOR_CHECK_PROVIDERS = [
1160
1234
  PlanCatalogDoctorCheck,
1161
1235
  DiscoverySnapshotDoctorCheck,
1162
1236
  UserPortDoctorCheck,
1163
- AdminManifestDoctorCheck
1237
+ AdminManifestDoctorCheck,
1238
+ IssuerIdentityDoctorCheck
1164
1239
  ];
1165
1240
 
1166
1241
  // src/prisma-blocks.ts
@@ -3758,6 +3833,7 @@ UserCommands = _ts_decorate14([
3758
3833
  DiscoverySnapshotDoctorCheck,
3759
3834
  DoctorCommands,
3760
3835
  DoctorFlow,
3836
+ IssuerIdentityDoctorCheck,
3761
3837
  LIMIT_FILTER_IMPORTS,
3762
3838
  LIMIT_FILTER_PROVIDER,
3763
3839
  MANIFEST_ACCESS_PORT_TOKEN,
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { MfaService, AdminAuditService, AdminManifestService, DiscoverySnapshot, ProviderSpec, DiscoveryScanner } from '@saasicat/nest';
1
+ import { MfaService, AdminAuditService, AdminManifestService, DiscoverySnapshot, IssuerIdentityInspector, ProviderSpec, DiscoveryScanner } from '@saasicat/nest';
2
2
  import { UserPort, PlatformUserDto, AuditQueryPort, AuditEntry, AdminManifest, ManifestAccessPort, PlanCatalog, UserManagementPort } from '@saasicat/core';
3
3
  import { Type, DynamicModule } from '@nestjs/common';
4
4
  import * as TypeScript from 'typescript';
@@ -311,6 +311,28 @@ declare class AdminManifestDoctorCheck implements DoctorCheck {
311
311
  constructor(manifest: AdminManifestService);
312
312
  run(): Promise<DoctorCheckResult>;
313
313
  }
314
+ /**
315
+ * The issuer identity, and what changing it would cost.
316
+ *
317
+ * A start compares the issuer in `config/saas.yaml` with the identity the
318
+ * installation recorded and refuses an undeclared difference, because moving a
319
+ * contract to another legal entity is a transfer and not an edit of a setting.
320
+ * This asks the same question without acting on it and says, while nothing has
321
+ * moved, what a change would cost.
322
+ *
323
+ * It does NOT turn a refusal into a report where the same application also
324
+ * mounts the platform's boot check: that check runs at `init()`, so the CLI
325
+ * process carrying it is refused before any command runs — with the same
326
+ * message, which is the point. The `refused` branch below is for a diagnostic
327
+ * that runs without the hook.
328
+ */
329
+ declare class IssuerIdentityDoctorCheck implements DoctorCheck {
330
+ private readonly issuer;
331
+ readonly id = "platform.issuer-identity";
332
+ readonly label = "Issuer identity against the recorded one";
333
+ constructor(issuer: IssuerIdentityInspector);
334
+ run(): Promise<DoctorCheckResult>;
335
+ }
314
336
  /**
315
337
  * Default list that consumers can spread in `CliContextModule.forRoot({ doctorChecks })`:
316
338
  *
@@ -1226,15 +1248,18 @@ interface CliContextModuleOptions {
1226
1248
  * — `<app> doctor` runs but returns no content. Consumers register
1227
1249
  * project-specific checks.
1228
1250
  *
1229
- * Note: if `defaultDoctorChecks: true`, the 4 platform standard checks
1230
- * (PlanCatalog/Discovery/UserPort/AdminManifest) are registered **in
1231
- * addition** to this list.
1251
+ * Note: if `defaultDoctorChecks: true`, the platform's own checks
1252
+ * `PLATFORM_DOCTOR_CHECK_PROVIDERS` are registered **in addition** to
1253
+ * this list. They are named there rather than here: a second list of them
1254
+ * in prose is the copy that goes stale.
1232
1255
  */
1233
1256
  doctorChecks?: ProviderSpec<DoctorCheck[]>;
1234
1257
  /**
1235
- * Default `false`. If `true`, the platform registers the four standard
1236
- * checks from `PLATFORM_DOCTOR_CHECK_PROVIDERS` in addition to
1237
- * `doctorChecks`. Recommended for all apps that take `<app> doctor` seriously.
1258
+ * Default `false`. If `true`, the platform registers the checks from
1259
+ * `PLATFORM_DOCTOR_CHECK_PROVIDERS` in addition to `doctorChecks`. They
1260
+ * resolve what `SaaSiCatModule` provides, so an application that wires the
1261
+ * platform's modules by hand registers the ones it can serve instead.
1262
+ * Recommended for all apps that take `<app> doctor` seriously.
1238
1263
  */
1239
1264
  defaultDoctorChecks?: boolean;
1240
1265
  /**
@@ -1402,4 +1427,4 @@ declare class UserCommands extends CommandRunner {
1402
1427
  parsePassword(val: string): string;
1403
1428
  }
1404
1429
 
1405
- export { AUDIT_QUERY_PORT_TOKEN, AdminCommands, AdminManifestDoctorCheck, AdminMfaSetupCommand, AdminWhoamiCommand, type ApplyResult, AuditCommands, AuditTailCommand, AuditTailFlow, type AuditTailOptions, type BlockAttributeKind, type BlockAttributes, CLI_CONTEXT_CONFIG_TOKEN, CONSTRAINTS_MARKER, type CheckSeverity, type CliContextConfig, CliContextModule, type CliContextModuleOptions, CliContextService, CliError, type CliIdentity, type ConstraintsOutcome, type ConstraintsReport, DEFAULT_MANIFEST_CHECKS, DOCTOR_CHECKS_TOKEN, type DbCatalogOccurrence, type DbCatalogResult, type DbCatalogShape, DiscoveryCommands, DiscoveryScanCommand, DiscoverySnapshotDoctorCheck, type DoctorCheck, type DoctorCheckResult, DoctorCommands, DoctorFlow, type DoctorReport, type EnableFkResult, type FieldMismatch, type FieldMismatchReason, type FieldSignature, type FkModelNames, type FkPointer, type FragmentBlocks, type InitOptions, type InitPlan, LIMIT_FILTER_IMPORTS, LIMIT_FILTER_PROVIDER, MANIFEST_ACCESS_PORT_TOKEN, MANIFEST_CHECKS_TOKEN, type ManifestCheck, ManifestCheckCommand, type ManifestCheckReport, type ManifestCheckResult, ManifestCliFlow, ManifestCommands, type ManifestDiff, ManifestDumpCommand, ManifestHashCommand, type ManifestRewriteOptions, ManifestValidateCommand, MfaSetupFlow, type MfaSetupOptions, type MfaSetupResult, type MissingBlockAttribute, type MissingEnumValue, type MissingField, type ModuleResolutionVerdict, type MoveTable, type MovedSetting, type MovedSettingOccurrence, type MovedSettingsResult, PLATFORM_DOCTOR_CHECK_PROVIDERS, type ParsedSchema, type PatchAppModuleOptions, type PatchOptionsFromPlan, type PatchResult, PlanCatalogDoctorCheck, type PlannedFile, type ProjectKeyResult, type QuotaProviderFile, type QuotaSpec, type RenameResult, type RenameTable, type RewriteResult, SCANNED_FOR_DB_CATALOG, SCANNED_FOR_MOVED_SETTINGS, SETTINGS_THAT_MOVED, type SchemaCheckReport, type TenantCascade, UI_VUE_SPECIFIER, USER_MANAGEMENT_PORT_TOKEN, USER_PORT_TOKEN, UserCommands, UserPortDoctorCheck, WHERE_DB_CATALOG_GOES, WHERE_IT_GOES, WhoAmIFlow, type WhoAmIResult, type WrittenSetting, appKeyPattern, appendConstraints, applyFragmentBlocks, applyTokens, assertModelsExist, assertValidAppKey, assertValidQuotaKey, blankStringLiterals, blockBodyLines, breaksContract, buildImportMap, checkSchema, constraintsFor, describeDbCatalogOccurrence, enableFkPointers, extractBlockNames, extractBlocks, extractEnumBlocks, extractEnumNames, extractFragmentBlocks, extractModelBlocks, extractModelNames, findDbCatalogBlocks, findFkPointers, findMovedSettings, foreignKeyOf, hasBackRelation, hasConstraints, isNoLongerPublic, isOneToOne, judgeModuleResolution, kebabCase, migrationCreatedBy, minimumQuotasPerPlan, modelsKeptPastTheTenant, namedImports, parseBlockAttributes, parseEnumValues, parseFields, parseQuota, parseSchema, pascalCase, patchAppModule, patchOptionsFor, planInit, quotaKeyPattern, readEffectiveModuleResolution, relationNameOf, removeProjectKey, reportConstraints, rewriteImports, rewriteManifest, rewriteNames, rewriteSubpath, settingsWrittenTo, stripLineComment, structuralOnly, tablesAddressedBy };
1430
+ export { AUDIT_QUERY_PORT_TOKEN, AdminCommands, AdminManifestDoctorCheck, AdminMfaSetupCommand, AdminWhoamiCommand, type ApplyResult, AuditCommands, AuditTailCommand, AuditTailFlow, type AuditTailOptions, type BlockAttributeKind, type BlockAttributes, CLI_CONTEXT_CONFIG_TOKEN, CONSTRAINTS_MARKER, type CheckSeverity, type CliContextConfig, CliContextModule, type CliContextModuleOptions, CliContextService, CliError, type CliIdentity, type ConstraintsOutcome, type ConstraintsReport, DEFAULT_MANIFEST_CHECKS, DOCTOR_CHECKS_TOKEN, type DbCatalogOccurrence, type DbCatalogResult, type DbCatalogShape, DiscoveryCommands, DiscoveryScanCommand, DiscoverySnapshotDoctorCheck, type DoctorCheck, type DoctorCheckResult, DoctorCommands, DoctorFlow, type DoctorReport, type EnableFkResult, type FieldMismatch, type FieldMismatchReason, type FieldSignature, type FkModelNames, type FkPointer, type FragmentBlocks, type InitOptions, type InitPlan, IssuerIdentityDoctorCheck, LIMIT_FILTER_IMPORTS, LIMIT_FILTER_PROVIDER, MANIFEST_ACCESS_PORT_TOKEN, MANIFEST_CHECKS_TOKEN, type ManifestCheck, ManifestCheckCommand, type ManifestCheckReport, type ManifestCheckResult, ManifestCliFlow, ManifestCommands, type ManifestDiff, ManifestDumpCommand, ManifestHashCommand, type ManifestRewriteOptions, ManifestValidateCommand, MfaSetupFlow, type MfaSetupOptions, type MfaSetupResult, type MissingBlockAttribute, type MissingEnumValue, type MissingField, type ModuleResolutionVerdict, type MoveTable, type MovedSetting, type MovedSettingOccurrence, type MovedSettingsResult, PLATFORM_DOCTOR_CHECK_PROVIDERS, type ParsedSchema, type PatchAppModuleOptions, type PatchOptionsFromPlan, type PatchResult, PlanCatalogDoctorCheck, type PlannedFile, type ProjectKeyResult, type QuotaProviderFile, type QuotaSpec, type RenameResult, type RenameTable, type RewriteResult, SCANNED_FOR_DB_CATALOG, SCANNED_FOR_MOVED_SETTINGS, SETTINGS_THAT_MOVED, type SchemaCheckReport, type TenantCascade, UI_VUE_SPECIFIER, USER_MANAGEMENT_PORT_TOKEN, USER_PORT_TOKEN, UserCommands, UserPortDoctorCheck, WHERE_DB_CATALOG_GOES, WHERE_IT_GOES, WhoAmIFlow, type WhoAmIResult, type WrittenSetting, appKeyPattern, appendConstraints, applyFragmentBlocks, applyTokens, assertModelsExist, assertValidAppKey, assertValidQuotaKey, blankStringLiterals, blockBodyLines, breaksContract, buildImportMap, checkSchema, constraintsFor, describeDbCatalogOccurrence, enableFkPointers, extractBlockNames, extractBlocks, extractEnumBlocks, extractEnumNames, extractFragmentBlocks, extractModelBlocks, extractModelNames, findDbCatalogBlocks, findFkPointers, findMovedSettings, foreignKeyOf, hasBackRelation, hasConstraints, isNoLongerPublic, isOneToOne, judgeModuleResolution, kebabCase, migrationCreatedBy, minimumQuotasPerPlan, modelsKeptPastTheTenant, namedImports, parseBlockAttributes, parseEnumValues, parseFields, parseQuota, parseSchema, pascalCase, patchAppModule, patchOptionsFor, planInit, quotaKeyPattern, readEffectiveModuleResolution, relationNameOf, removeProjectKey, reportConstraints, rewriteImports, rewriteManifest, rewriteNames, rewriteSubpath, settingsWrittenTo, stripLineComment, structuralOnly, tablesAddressedBy };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { MfaService, AdminAuditService, AdminManifestService, DiscoverySnapshot, ProviderSpec, DiscoveryScanner } from '@saasicat/nest';
1
+ import { MfaService, AdminAuditService, AdminManifestService, DiscoverySnapshot, IssuerIdentityInspector, ProviderSpec, DiscoveryScanner } from '@saasicat/nest';
2
2
  import { UserPort, PlatformUserDto, AuditQueryPort, AuditEntry, AdminManifest, ManifestAccessPort, PlanCatalog, UserManagementPort } from '@saasicat/core';
3
3
  import { Type, DynamicModule } from '@nestjs/common';
4
4
  import * as TypeScript from 'typescript';
@@ -311,6 +311,28 @@ declare class AdminManifestDoctorCheck implements DoctorCheck {
311
311
  constructor(manifest: AdminManifestService);
312
312
  run(): Promise<DoctorCheckResult>;
313
313
  }
314
+ /**
315
+ * The issuer identity, and what changing it would cost.
316
+ *
317
+ * A start compares the issuer in `config/saas.yaml` with the identity the
318
+ * installation recorded and refuses an undeclared difference, because moving a
319
+ * contract to another legal entity is a transfer and not an edit of a setting.
320
+ * This asks the same question without acting on it and says, while nothing has
321
+ * moved, what a change would cost.
322
+ *
323
+ * It does NOT turn a refusal into a report where the same application also
324
+ * mounts the platform's boot check: that check runs at `init()`, so the CLI
325
+ * process carrying it is refused before any command runs — with the same
326
+ * message, which is the point. The `refused` branch below is for a diagnostic
327
+ * that runs without the hook.
328
+ */
329
+ declare class IssuerIdentityDoctorCheck implements DoctorCheck {
330
+ private readonly issuer;
331
+ readonly id = "platform.issuer-identity";
332
+ readonly label = "Issuer identity against the recorded one";
333
+ constructor(issuer: IssuerIdentityInspector);
334
+ run(): Promise<DoctorCheckResult>;
335
+ }
314
336
  /**
315
337
  * Default list that consumers can spread in `CliContextModule.forRoot({ doctorChecks })`:
316
338
  *
@@ -1226,15 +1248,18 @@ interface CliContextModuleOptions {
1226
1248
  * — `<app> doctor` runs but returns no content. Consumers register
1227
1249
  * project-specific checks.
1228
1250
  *
1229
- * Note: if `defaultDoctorChecks: true`, the 4 platform standard checks
1230
- * (PlanCatalog/Discovery/UserPort/AdminManifest) are registered **in
1231
- * addition** to this list.
1251
+ * Note: if `defaultDoctorChecks: true`, the platform's own checks
1252
+ * `PLATFORM_DOCTOR_CHECK_PROVIDERS` are registered **in addition** to
1253
+ * this list. They are named there rather than here: a second list of them
1254
+ * in prose is the copy that goes stale.
1232
1255
  */
1233
1256
  doctorChecks?: ProviderSpec<DoctorCheck[]>;
1234
1257
  /**
1235
- * Default `false`. If `true`, the platform registers the four standard
1236
- * checks from `PLATFORM_DOCTOR_CHECK_PROVIDERS` in addition to
1237
- * `doctorChecks`. Recommended for all apps that take `<app> doctor` seriously.
1258
+ * Default `false`. If `true`, the platform registers the checks from
1259
+ * `PLATFORM_DOCTOR_CHECK_PROVIDERS` in addition to `doctorChecks`. They
1260
+ * resolve what `SaaSiCatModule` provides, so an application that wires the
1261
+ * platform's modules by hand registers the ones it can serve instead.
1262
+ * Recommended for all apps that take `<app> doctor` seriously.
1238
1263
  */
1239
1264
  defaultDoctorChecks?: boolean;
1240
1265
  /**
@@ -1402,4 +1427,4 @@ declare class UserCommands extends CommandRunner {
1402
1427
  parsePassword(val: string): string;
1403
1428
  }
1404
1429
 
1405
- export { AUDIT_QUERY_PORT_TOKEN, AdminCommands, AdminManifestDoctorCheck, AdminMfaSetupCommand, AdminWhoamiCommand, type ApplyResult, AuditCommands, AuditTailCommand, AuditTailFlow, type AuditTailOptions, type BlockAttributeKind, type BlockAttributes, CLI_CONTEXT_CONFIG_TOKEN, CONSTRAINTS_MARKER, type CheckSeverity, type CliContextConfig, CliContextModule, type CliContextModuleOptions, CliContextService, CliError, type CliIdentity, type ConstraintsOutcome, type ConstraintsReport, DEFAULT_MANIFEST_CHECKS, DOCTOR_CHECKS_TOKEN, type DbCatalogOccurrence, type DbCatalogResult, type DbCatalogShape, DiscoveryCommands, DiscoveryScanCommand, DiscoverySnapshotDoctorCheck, type DoctorCheck, type DoctorCheckResult, DoctorCommands, DoctorFlow, type DoctorReport, type EnableFkResult, type FieldMismatch, type FieldMismatchReason, type FieldSignature, type FkModelNames, type FkPointer, type FragmentBlocks, type InitOptions, type InitPlan, LIMIT_FILTER_IMPORTS, LIMIT_FILTER_PROVIDER, MANIFEST_ACCESS_PORT_TOKEN, MANIFEST_CHECKS_TOKEN, type ManifestCheck, ManifestCheckCommand, type ManifestCheckReport, type ManifestCheckResult, ManifestCliFlow, ManifestCommands, type ManifestDiff, ManifestDumpCommand, ManifestHashCommand, type ManifestRewriteOptions, ManifestValidateCommand, MfaSetupFlow, type MfaSetupOptions, type MfaSetupResult, type MissingBlockAttribute, type MissingEnumValue, type MissingField, type ModuleResolutionVerdict, type MoveTable, type MovedSetting, type MovedSettingOccurrence, type MovedSettingsResult, PLATFORM_DOCTOR_CHECK_PROVIDERS, type ParsedSchema, type PatchAppModuleOptions, type PatchOptionsFromPlan, type PatchResult, PlanCatalogDoctorCheck, type PlannedFile, type ProjectKeyResult, type QuotaProviderFile, type QuotaSpec, type RenameResult, type RenameTable, type RewriteResult, SCANNED_FOR_DB_CATALOG, SCANNED_FOR_MOVED_SETTINGS, SETTINGS_THAT_MOVED, type SchemaCheckReport, type TenantCascade, UI_VUE_SPECIFIER, USER_MANAGEMENT_PORT_TOKEN, USER_PORT_TOKEN, UserCommands, UserPortDoctorCheck, WHERE_DB_CATALOG_GOES, WHERE_IT_GOES, WhoAmIFlow, type WhoAmIResult, type WrittenSetting, appKeyPattern, appendConstraints, applyFragmentBlocks, applyTokens, assertModelsExist, assertValidAppKey, assertValidQuotaKey, blankStringLiterals, blockBodyLines, breaksContract, buildImportMap, checkSchema, constraintsFor, describeDbCatalogOccurrence, enableFkPointers, extractBlockNames, extractBlocks, extractEnumBlocks, extractEnumNames, extractFragmentBlocks, extractModelBlocks, extractModelNames, findDbCatalogBlocks, findFkPointers, findMovedSettings, foreignKeyOf, hasBackRelation, hasConstraints, isNoLongerPublic, isOneToOne, judgeModuleResolution, kebabCase, migrationCreatedBy, minimumQuotasPerPlan, modelsKeptPastTheTenant, namedImports, parseBlockAttributes, parseEnumValues, parseFields, parseQuota, parseSchema, pascalCase, patchAppModule, patchOptionsFor, planInit, quotaKeyPattern, readEffectiveModuleResolution, relationNameOf, removeProjectKey, reportConstraints, rewriteImports, rewriteManifest, rewriteNames, rewriteSubpath, settingsWrittenTo, stripLineComment, structuralOnly, tablesAddressedBy };
1430
+ export { AUDIT_QUERY_PORT_TOKEN, AdminCommands, AdminManifestDoctorCheck, AdminMfaSetupCommand, AdminWhoamiCommand, type ApplyResult, AuditCommands, AuditTailCommand, AuditTailFlow, type AuditTailOptions, type BlockAttributeKind, type BlockAttributes, CLI_CONTEXT_CONFIG_TOKEN, CONSTRAINTS_MARKER, type CheckSeverity, type CliContextConfig, CliContextModule, type CliContextModuleOptions, CliContextService, CliError, type CliIdentity, type ConstraintsOutcome, type ConstraintsReport, DEFAULT_MANIFEST_CHECKS, DOCTOR_CHECKS_TOKEN, type DbCatalogOccurrence, type DbCatalogResult, type DbCatalogShape, DiscoveryCommands, DiscoveryScanCommand, DiscoverySnapshotDoctorCheck, type DoctorCheck, type DoctorCheckResult, DoctorCommands, DoctorFlow, type DoctorReport, type EnableFkResult, type FieldMismatch, type FieldMismatchReason, type FieldSignature, type FkModelNames, type FkPointer, type FragmentBlocks, type InitOptions, type InitPlan, IssuerIdentityDoctorCheck, LIMIT_FILTER_IMPORTS, LIMIT_FILTER_PROVIDER, MANIFEST_ACCESS_PORT_TOKEN, MANIFEST_CHECKS_TOKEN, type ManifestCheck, ManifestCheckCommand, type ManifestCheckReport, type ManifestCheckResult, ManifestCliFlow, ManifestCommands, type ManifestDiff, ManifestDumpCommand, ManifestHashCommand, type ManifestRewriteOptions, ManifestValidateCommand, MfaSetupFlow, type MfaSetupOptions, type MfaSetupResult, type MissingBlockAttribute, type MissingEnumValue, type MissingField, type ModuleResolutionVerdict, type MoveTable, type MovedSetting, type MovedSettingOccurrence, type MovedSettingsResult, PLATFORM_DOCTOR_CHECK_PROVIDERS, type ParsedSchema, type PatchAppModuleOptions, type PatchOptionsFromPlan, type PatchResult, PlanCatalogDoctorCheck, type PlannedFile, type ProjectKeyResult, type QuotaProviderFile, type QuotaSpec, type RenameResult, type RenameTable, type RewriteResult, SCANNED_FOR_DB_CATALOG, SCANNED_FOR_MOVED_SETTINGS, SETTINGS_THAT_MOVED, type SchemaCheckReport, type TenantCascade, UI_VUE_SPECIFIER, USER_MANAGEMENT_PORT_TOKEN, USER_PORT_TOKEN, UserCommands, UserPortDoctorCheck, WHERE_DB_CATALOG_GOES, WHERE_IT_GOES, WhoAmIFlow, type WhoAmIResult, type WrittenSetting, appKeyPattern, appendConstraints, applyFragmentBlocks, applyTokens, assertModelsExist, assertValidAppKey, assertValidQuotaKey, blankStringLiterals, blockBodyLines, breaksContract, buildImportMap, checkSchema, constraintsFor, describeDbCatalogOccurrence, enableFkPointers, extractBlockNames, extractBlocks, extractEnumBlocks, extractEnumNames, extractFragmentBlocks, extractModelBlocks, extractModelNames, findDbCatalogBlocks, findFkPointers, findMovedSettings, foreignKeyOf, hasBackRelation, hasConstraints, isNoLongerPublic, isOneToOne, judgeModuleResolution, kebabCase, migrationCreatedBy, minimumQuotasPerPlan, modelsKeptPastTheTenant, namedImports, parseBlockAttributes, parseEnumValues, parseFields, parseQuota, parseSchema, pascalCase, patchAppModule, patchOptionsFor, planInit, quotaKeyPattern, readEffectiveModuleResolution, relationNameOf, removeProjectKey, reportConstraints, rewriteImports, rewriteManifest, rewriteNames, rewriteSubpath, settingsWrittenTo, stripLineComment, structuralOnly, tablesAddressedBy };
package/dist/index.js CHANGED
@@ -869,7 +869,7 @@ __name(collectComponentKeys, "collectComponentKeys");
869
869
 
870
870
  // src/default-doctor-checks.ts
871
871
  import { Inject as Inject6, Injectable as Injectable7 } from "@nestjs/common";
872
- import { AdminManifestService, DISCOVERY_SNAPSHOT_TOKEN, PLAN_CATALOG_TOKEN } from "@saasicat/nest";
872
+ import { AdminManifestService, DISCOVERY_SNAPSHOT_TOKEN, IssuerIdentityInspector, PLAN_CATALOG_TOKEN } from "@saasicat/nest";
873
873
  function _ts_decorate7(decorators, target, key, desc) {
874
874
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
875
875
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1021,11 +1021,85 @@ AdminManifestDoctorCheck = _ts_decorate7([
1021
1021
  typeof AdminManifestService === "undefined" ? Object : AdminManifestService
1022
1022
  ])
1023
1023
  ], AdminManifestDoctorCheck);
1024
+ var IssuerIdentityDoctorCheck = class {
1025
+ static {
1026
+ __name(this, "IssuerIdentityDoctorCheck");
1027
+ }
1028
+ issuer;
1029
+ id = "platform.issuer-identity";
1030
+ label = "Issuer identity against the recorded one";
1031
+ constructor(issuer) {
1032
+ this.issuer = issuer;
1033
+ }
1034
+ async run() {
1035
+ const verdict = await this.issuer.inspect();
1036
+ if (verdict.kind === "refused") {
1037
+ return {
1038
+ severity: "error",
1039
+ message: verdict.refusal,
1040
+ // The number and the identifiers, not the rows: `DoctorReport`
1041
+ // is serialised as JSON, and the dates on a row would come out
1042
+ // as timestamps beside the same dates already written as days in
1043
+ // the message above.
1044
+ // One unknown answered once: `null` for both where the
1045
+ // contracts could not be read, rather than a null count beside
1046
+ // an empty list that reads as "none".
1047
+ details: verdict.running ? {
1048
+ runningContracts: verdict.running.total,
1049
+ named: verdict.running.contracts.map((row) => row.id)
1050
+ } : {
1051
+ runningContracts: null,
1052
+ named: null
1053
+ }
1054
+ };
1055
+ }
1056
+ if (verdict.kind === "not-compared") {
1057
+ return {
1058
+ severity: "warning",
1059
+ message: `The issuer in the file is compared with nothing \u2014 ${verdict.why} \u2014 so a start that names another legal entity than the last one is not refused.`
1060
+ };
1061
+ }
1062
+ const change = verdict.change;
1063
+ switch (change.kind) {
1064
+ case "none-named":
1065
+ return {
1066
+ severity: "ok",
1067
+ message: "No issuer is named, and none was recorded."
1068
+ };
1069
+ case "first-naming":
1070
+ return {
1071
+ severity: "ok",
1072
+ message: `'${change.identity.legalName}' is named for the first time; no contract can name another.`
1073
+ };
1074
+ case "corrected":
1075
+ return {
1076
+ severity: "ok",
1077
+ message: `A correction of '${change.recorded.legalName}' is declared: ${change.reason}. This is what the start found; whether it has been recorded is what \`GET /admin/settings\` shows, and \`issuer.correctionOf\` may be dropped once it does.`
1078
+ };
1079
+ case "unchanged": {
1080
+ const running = await this.issuer.runningContractCount();
1081
+ const weighedAgainst = running === null ? "" : ` ${running} contract(s) are running, and their issuer copies do not follow a change.`;
1082
+ return {
1083
+ severity: "ok",
1084
+ message: `'${change.identity.legalName}' is what the installation recorded.` + weighedAgainst + " Changing the legal name or a tax identifier needs `issuer.correctionOf` beside the values it replaces; the address and the contact details do not."
1085
+ };
1086
+ }
1087
+ }
1088
+ }
1089
+ };
1090
+ IssuerIdentityDoctorCheck = _ts_decorate7([
1091
+ Injectable7(),
1092
+ _ts_metadata7("design:type", Function),
1093
+ _ts_metadata7("design:paramtypes", [
1094
+ typeof IssuerIdentityInspector === "undefined" ? Object : IssuerIdentityInspector
1095
+ ])
1096
+ ], IssuerIdentityDoctorCheck);
1024
1097
  var PLATFORM_DOCTOR_CHECK_PROVIDERS = [
1025
1098
  PlanCatalogDoctorCheck,
1026
1099
  DiscoverySnapshotDoctorCheck,
1027
1100
  UserPortDoctorCheck,
1028
- AdminManifestDoctorCheck
1101
+ AdminManifestDoctorCheck,
1102
+ IssuerIdentityDoctorCheck
1029
1103
  ];
1030
1104
 
1031
1105
  // src/prisma-blocks.ts
@@ -3622,6 +3696,7 @@ export {
3622
3696
  DiscoverySnapshotDoctorCheck,
3623
3697
  DoctorCommands,
3624
3698
  DoctorFlow,
3699
+ IssuerIdentityDoctorCheck,
3625
3700
  LIMIT_FILTER_IMPORTS,
3626
3701
  LIMIT_FILTER_PROVIDER,
3627
3702
  MANIFEST_ACCESS_PORT_TOKEN,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasicat/cli",
3
- "version": "1.0.0-rc.18",
3
+ "version": "1.0.0-rc.19",
4
4
  "description": "CLI helpers for SaaS platform consumers. Provides CliContextService (identity, MFA, production confirm, audit tag).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -30,9 +30,9 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "qrcode-terminal": "^0.12.0",
33
- "@saasicat/nest": "^1.0.0-rc.18",
34
- "@saasicat/spec": "^1.0.0-rc.18",
35
- "@saasicat/core": "^1.0.0-rc.18"
33
+ "@saasicat/nest": "^1.0.0-rc.19",
34
+ "@saasicat/spec": "^1.0.0-rc.19",
35
+ "@saasicat/core": "^1.0.0-rc.19"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@nestjs/common": "^11.0.0",