V13-FE-011: finalize search list layout slice
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
export type KbxAiCapability = 'explain' | 'suggest' | 'draft' | 'execute'
|
||||
|
||||
export interface KbxAiScreenContext {
|
||||
screenId: string
|
||||
screenVersion: string
|
||||
entityId?: string
|
||||
selectedIds?: string[]
|
||||
filters?: Record<string, unknown>
|
||||
allowedCapabilities: KbxAiCapability[]
|
||||
}
|
||||
|
||||
export interface KbxAiEvidence {
|
||||
label: string
|
||||
sourceType: 'domain' | 'api' | 'audit' | 'document' | 'rule'
|
||||
reference?: string
|
||||
}
|
||||
|
||||
export interface KbxAiProposalChange {
|
||||
field: string
|
||||
label: string
|
||||
before?: unknown
|
||||
after?: unknown
|
||||
}
|
||||
|
||||
export type KbxAiProposalValidationState = 'pending' | 'validated' | 'invalid' | 'stale'
|
||||
|
||||
export interface KbxAiProposalValidation {
|
||||
state: KbxAiProposalValidationState
|
||||
message?: string
|
||||
validatedAt?: string
|
||||
}
|
||||
|
||||
export interface KbxAiProposal {
|
||||
id: string
|
||||
type: string
|
||||
title: string
|
||||
explanation: string
|
||||
capability: Exclude<KbxAiCapability, 'explain'>
|
||||
targets?: { entityType: string; entityId: string }[]
|
||||
proposedChanges?: KbxAiProposalChange[]
|
||||
evidence?: KbxAiEvidence[]
|
||||
confidence?: number
|
||||
requiredPermission?: string
|
||||
validation?: KbxAiProposalValidation
|
||||
}
|
||||
|
||||
export interface KbxAiAskRequest {
|
||||
question: string
|
||||
context: KbxAiScreenContext
|
||||
}
|
||||
|
||||
export interface KbxAiAnswerAction {
|
||||
id: string
|
||||
label: string
|
||||
kind: 'navigate' | 'filter' | 'proposal'
|
||||
requiredCapability?: KbxAiCapability
|
||||
requiredPermission?: string
|
||||
}
|
||||
|
||||
export interface KbxAiAnswer {
|
||||
answer: string
|
||||
actions?: KbxAiAnswerAction[]
|
||||
proposal?: KbxAiProposal
|
||||
evidence?: KbxAiEvidence[]
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
export type KbxHttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
|
||||
export type KbxApiOperationKind = 'query' | 'command' | 'upload'
|
||||
export type KbxIdempotencyPolicy = 'none' | 'supported' | 'required'
|
||||
|
||||
export interface KbxApiOperationDefinition {
|
||||
id: string
|
||||
method: KbxHttpMethod
|
||||
path: string
|
||||
permission?: string | null
|
||||
kind: KbxApiOperationKind
|
||||
idempotency: KbxIdempotencyPolicy
|
||||
successStatuses: readonly number[]
|
||||
contentType?: string
|
||||
responseType?: 'json' | 'blob'
|
||||
}
|
||||
|
||||
export interface KbxApiRequestOptions<TBody = unknown> {
|
||||
path?: Record<string, string | number>
|
||||
query?: object
|
||||
body?: TBody
|
||||
headers?: Record<string, string>
|
||||
idempotencyKey?: string
|
||||
responseType?: 'json' | 'blob'
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
export type KbxAuditSource = 'user' | 'system' | 'api' | 'import' | 'ai' | 'batch'
|
||||
|
||||
export interface KbxAuditEntry {
|
||||
id: string
|
||||
occurredAt: string
|
||||
actor: {
|
||||
type: KbxAuditSource
|
||||
displayName: string
|
||||
}
|
||||
action: string
|
||||
changes?: Array<{
|
||||
field: string
|
||||
label: string
|
||||
before?: unknown
|
||||
after?: unknown
|
||||
}>
|
||||
reason?: string
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
export type KbxPermissionRisk = 'low' | 'medium' | 'high'
|
||||
export type KbxPermissionPresentation = 'hide' | 'disable'
|
||||
|
||||
export interface KbxPermissionDefinition {
|
||||
id: string
|
||||
module: 'OMS' | 'ERP' | 'WMS' | 'COMMON'
|
||||
resource: string
|
||||
action: string
|
||||
risk: KbxPermissionRisk
|
||||
description: string
|
||||
presentation: KbxPermissionPresentation
|
||||
backendRequired: boolean
|
||||
}
|
||||
|
||||
export interface KbxSensitiveDataPolicy {
|
||||
id: string
|
||||
fields: string[]
|
||||
defaultExposure: 'masked'
|
||||
viewPermission: string
|
||||
revealPermission: string
|
||||
unmaskedExportPermission: string
|
||||
auditRequired: boolean
|
||||
aiExposure: 'masked-only' | 'deny'
|
||||
telemetryExposure: 'never'
|
||||
reasonRequired: boolean
|
||||
}
|
||||
|
||||
export interface KbxAuthorizationDecision {
|
||||
allowed: boolean
|
||||
permission: string
|
||||
presentation: KbxPermissionPresentation
|
||||
reason?: string
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { KbxDensity } from './preference'
|
||||
|
||||
export type KbxCatalogState =
|
||||
| 'default'
|
||||
| 'idle'
|
||||
| 'ready'
|
||||
| 'refreshing'
|
||||
| 'readonly'
|
||||
| 'disabled'
|
||||
| 'required'
|
||||
| 'error'
|
||||
| 'loading'
|
||||
| 'keyboard'
|
||||
| 'changed'
|
||||
| 'warning'
|
||||
| 'ai-suggested'
|
||||
| 'empty'
|
||||
|
||||
export interface KbxCatalogScenario {
|
||||
id: string
|
||||
label: string
|
||||
state: KbxCatalogState
|
||||
density?: KbxDensity
|
||||
description?: string
|
||||
}
|
||||
|
||||
export interface KbxComponentCatalogEntry {
|
||||
component: string
|
||||
group: 'input' | 'command' | 'grid' | 'feedback' | 'overlay' | 'template' | 'wms' | 'shell'
|
||||
scenarios: KbxCatalogScenario[]
|
||||
accessibility: {
|
||||
keyboard: boolean
|
||||
focusVisible: boolean
|
||||
labelRequired?: boolean
|
||||
colorIndependentStatus?: boolean
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
export type KbxCommandGroup = 'query' | 'edit' | 'workflow' | 'output' | 'more'
|
||||
export type KbxCommandVariant = 'primary' | 'secondary' | 'danger' | 'ghost'
|
||||
export interface KbxCommandConfirmDefinition { title:string; detail:string; level?:'low'|'medium'|'high'; confirmLabel?:string }
|
||||
|
||||
export interface KbxCommandDefinition {
|
||||
id: string
|
||||
label: string
|
||||
group: KbxCommandGroup
|
||||
variant?: KbxCommandVariant
|
||||
shortcut?: string
|
||||
permission?: string
|
||||
/** Optional state-specific authorization for one visual command (e.g. create vs update save). */
|
||||
permissionByStatus?: Record<string, string>
|
||||
icon?: string
|
||||
requiresSelection?: boolean
|
||||
minSelection?: number
|
||||
maxSelection?: number
|
||||
/** Keep the command visible but disabled outside these business states. */
|
||||
allowedStatuses?: string[]
|
||||
/** Save-like commands can be disabled until the page is dirty. */
|
||||
requiresDirty?: boolean
|
||||
/** Workflow commits can require the current record to be saved first. */
|
||||
requiresClean?: boolean
|
||||
disabledReason?: string
|
||||
confirm?: KbxCommandConfirmDefinition
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
export type KbxConfigurationValueType =
|
||||
| 'string'
|
||||
| 'boolean'
|
||||
| 'integer'
|
||||
| 'enum'
|
||||
| 'uri'
|
||||
| 'connection-string'
|
||||
|
||||
export interface KbxConfigurationSettingDefinition {
|
||||
key: string
|
||||
env: string
|
||||
category: string
|
||||
type: KbxConfigurationValueType
|
||||
allowedValues?: readonly string[]
|
||||
default?: string | number | boolean
|
||||
minimum?: number
|
||||
maximum?: number
|
||||
secret: boolean
|
||||
restartRequired: boolean
|
||||
requiredIn?: readonly string[]
|
||||
requiredWhen?: { key: string; equals: string | number | boolean }
|
||||
allowedSources?: readonly string[]
|
||||
}
|
||||
|
||||
export interface KbxEnvironmentProfileDefinition {
|
||||
id: 'Development' | 'Test' | 'Staging' | 'Production'
|
||||
artifactPromotion: boolean
|
||||
secretSources: readonly string[]
|
||||
migrationStrategy: string
|
||||
providerNetwork: 'forbidden' | 'opt-in'
|
||||
requireHttps: boolean
|
||||
providerEndpointOverrideAllowed: boolean
|
||||
requiredGates: readonly string[]
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
import { getKbxField, type KbxKnownFieldKey } from './generated/fieldCatalog'
|
||||
|
||||
export type KbxImportStatus =
|
||||
| 'created'
|
||||
| 'uploaded'
|
||||
| 'mapping-required'
|
||||
| 'validating'
|
||||
| 'validated'
|
||||
| 'committing'
|
||||
| 'completed'
|
||||
| 'partially-completed'
|
||||
| 'failed'
|
||||
| 'cancelled'
|
||||
|
||||
export type KbxImportMappingSource = 'exact' | 'alias' | 'saved' | 'ai' | 'manual'
|
||||
|
||||
export interface KbxImportFieldDefinition {
|
||||
key: string
|
||||
label: string
|
||||
aliases?: string[]
|
||||
dataType:
|
||||
| 'text'
|
||||
| 'code'
|
||||
| 'integer'
|
||||
| 'decimal'
|
||||
| 'quantity'
|
||||
| 'money'
|
||||
| 'date'
|
||||
| 'datetime'
|
||||
| 'boolean'
|
||||
| 'lookup'
|
||||
required?: boolean
|
||||
maxLength?: number
|
||||
precision?: number
|
||||
scale?: number
|
||||
lookupEntity?: string
|
||||
importable?: boolean
|
||||
exportable?: boolean
|
||||
helpText?: string
|
||||
sensitive?: boolean
|
||||
masking?: 'name' | 'phone' | 'address' | 'partial'
|
||||
}
|
||||
|
||||
export interface KbxImportDefinition {
|
||||
id: string
|
||||
screenId: string
|
||||
entity: string
|
||||
title: string
|
||||
fields: KbxImportFieldDefinition[]
|
||||
allowCreate: boolean
|
||||
allowUpdate: boolean
|
||||
maxFileSizeBytes?: number
|
||||
maxRows?: number
|
||||
}
|
||||
|
||||
export interface KbxImportMapping {
|
||||
sourceColumn: string
|
||||
targetField: string | null
|
||||
source: KbxImportMappingSource
|
||||
confidence?: number
|
||||
reason?: string
|
||||
}
|
||||
|
||||
export interface KbxImportValidationError {
|
||||
rowNumber: number
|
||||
field?: string
|
||||
sourceColumn?: string
|
||||
code: string
|
||||
message: string
|
||||
severity: 'error' | 'warning'
|
||||
}
|
||||
|
||||
export interface KbxImportFailure {
|
||||
code: string
|
||||
title: string
|
||||
detail?: string
|
||||
recoverable?: boolean
|
||||
}
|
||||
|
||||
export interface KbxImportSession {
|
||||
id: string
|
||||
importType: string
|
||||
screenId: string
|
||||
fileName: string
|
||||
status: KbxImportStatus
|
||||
totalRows: number
|
||||
validRows: number
|
||||
invalidRows: number
|
||||
warningRows: number
|
||||
createdRows: number
|
||||
updatedRows: number
|
||||
progressPercent: number
|
||||
mapping: KbxImportMapping[]
|
||||
sourceColumns: string[]
|
||||
errors?: KbxImportValidationError[]
|
||||
failure?: KbxImportFailure
|
||||
createdAt: string
|
||||
completedAt?: string
|
||||
}
|
||||
|
||||
export interface KbxImportProgressEvent {
|
||||
sessionId: string
|
||||
status: KbxImportStatus
|
||||
progressPercent: number
|
||||
totalRows: number
|
||||
processedRows: number
|
||||
validRows: number
|
||||
invalidRows: number
|
||||
warningRows: number
|
||||
message?: string
|
||||
}
|
||||
|
||||
export interface KbxSavedImportMapping {
|
||||
id: string
|
||||
importType: string
|
||||
name: string
|
||||
mappings: KbxImportMapping[]
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Materialize Excel metadata from the canonical KBX Field Dictionary.
|
||||
* Screen/import definitions may select fields, but should not duplicate label/type/length/alias metadata.
|
||||
*/
|
||||
export function kbxImportField(
|
||||
key: KbxKnownFieldKey,
|
||||
overrides: Partial<KbxImportFieldDefinition> = {},
|
||||
): KbxImportFieldDefinition {
|
||||
const field = getKbxField(key) as any
|
||||
if (!field.importable && overrides.importable !== true) {
|
||||
throw new Error(`${key} is not importable in the KBX field dictionary.`)
|
||||
}
|
||||
return {
|
||||
key,
|
||||
label: field.label,
|
||||
aliases: field.aliases ?? [],
|
||||
dataType: field.dataType,
|
||||
required: Boolean(field.required),
|
||||
maxLength: field.maxLength,
|
||||
precision: field.precision,
|
||||
scale: field.scale,
|
||||
lookupEntity: field.lookupEntity,
|
||||
importable: Boolean(field.importable),
|
||||
exportable: Boolean(field.exportable),
|
||||
helpText: field.helpText,
|
||||
sensitive: Boolean(field.sensitive),
|
||||
masking: field.masking,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
export type KbxExperimentRuntimeState = 'draft' | 'running' | 'paused' | 'rolled-back' | 'graduated' | 'completed'
|
||||
|
||||
export interface KbxExperimentAssignment {
|
||||
experimentId: string
|
||||
flagId: string
|
||||
screenId: string
|
||||
enrolled: boolean
|
||||
variant: string
|
||||
state: KbxExperimentRuntimeState
|
||||
}
|
||||
|
||||
export interface KbxExperimentAssignmentsResponse { assignments: KbxExperimentAssignment[] }
|
||||
|
||||
export interface KbxExperimentVariantMetric {
|
||||
variant: string
|
||||
exposures: number
|
||||
taskCompletions: number
|
||||
interactionsPerTask?: number | null
|
||||
taskCompletionP95Ms?: number | null
|
||||
validationFailureRate?: number | null
|
||||
}
|
||||
|
||||
export interface KbxExperimentOverviewRow {
|
||||
experimentId: string
|
||||
screenId: string
|
||||
state: KbxExperimentRuntimeState
|
||||
rolloutPercent: number
|
||||
killSwitch: boolean
|
||||
decision: 'inconclusive' | 'guardrail-breach' | 'candidate' | 'neutral' | 'rolled-back'
|
||||
variants: KbxExperimentVariantMetric[]
|
||||
updatedAt?: string | null
|
||||
}
|
||||
|
||||
export interface KbxExperimentOverviewResponse { items: KbxExperimentOverviewRow[] }
|
||||
export interface KbxExperimentRolloutRequest { rolloutPercent: number; state: 'running' | 'paused'; reason: string }
|
||||
export interface KbxExperimentRollbackRequest { reason: string }
|
||||
@@ -0,0 +1,67 @@
|
||||
export type KbxExternalDataFreshnessMode = 'strict' | 'stale-while-revalidate' | 'provider-defined'
|
||||
export type KbxExternalDataState = 'fresh' | 'stale' | 'expired' | 'unavailable'
|
||||
export type KbxRawSnapshotRetention = 'none' | 'hash-only' | 'encrypted-raw'
|
||||
|
||||
export interface KbxExternalDataDatasetDefinition {
|
||||
id: string
|
||||
providerId: string
|
||||
providerOperationId: string
|
||||
canonicalType: string
|
||||
normalizer: string
|
||||
normalizerVersion: string
|
||||
cacheKeyFields: readonly string[]
|
||||
freshness: {
|
||||
mode: KbxExternalDataFreshnessMode
|
||||
freshForSeconds: number | null
|
||||
maxStaleSeconds: number | null
|
||||
backgroundRefresh: boolean
|
||||
requireExplicitServicePolicy?: boolean
|
||||
}
|
||||
snapshot: {
|
||||
rawRetention: KbxRawSnapshotRetention
|
||||
normalizedRetentionDays: number
|
||||
}
|
||||
ui: {
|
||||
sourceLabel: string
|
||||
showProviderObservedAt: boolean
|
||||
showReceivedAt: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface KbxExternalDataProvenance {
|
||||
datasetId: string
|
||||
providerId: string
|
||||
providerOperationId: string
|
||||
sourceLabel: string
|
||||
state: KbxExternalDataState
|
||||
providerObservedAt?: string | null
|
||||
requestedAt: string
|
||||
receivedAt: string
|
||||
ingestedAt: string
|
||||
freshUntil?: string | null
|
||||
usableUntil?: string | null
|
||||
payloadSha256: string
|
||||
normalizerVersion: string
|
||||
cacheHit: boolean
|
||||
refreshInProgress?: boolean
|
||||
warning?: string
|
||||
}
|
||||
|
||||
export interface KbxExternalDataEnvelope<T> {
|
||||
data: T | null
|
||||
provenance: KbxExternalDataProvenance
|
||||
}
|
||||
|
||||
export interface KbxExternalDataStatusRow {
|
||||
datasetId: string
|
||||
providerId: string
|
||||
sourceLabel: string
|
||||
state: KbxExternalDataState
|
||||
cacheEntries: number
|
||||
lastReceivedAt?: string | null
|
||||
oldestFreshUntil?: string | null
|
||||
staleEntries: number
|
||||
unavailableEntries: number
|
||||
}
|
||||
|
||||
export interface KbxExternalDataStatusResponse { items: KbxExternalDataStatusRow[] }
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { KbxLookupDefinition } from './lookup'
|
||||
import type { KbxKnownFieldKey } from './generated/fieldCatalog'
|
||||
|
||||
export type KbxFieldDataType =
|
||||
| 'text'
|
||||
| 'code'
|
||||
| 'integer'
|
||||
| 'decimal'
|
||||
| 'quantity'
|
||||
| 'money'
|
||||
| 'date'
|
||||
| 'datetime'
|
||||
| 'boolean'
|
||||
| 'lookup'
|
||||
| 'status'
|
||||
|
||||
export interface KbxFieldDefinition<T = unknown> {
|
||||
/** Canonical fields should use KbxKnownFieldKey. string remains for local/read-model fields during staged adoption. */
|
||||
key: KbxKnownFieldKey | (string & {})
|
||||
label: string
|
||||
aliases?: string[]
|
||||
dataType: KbxFieldDataType
|
||||
required?: boolean
|
||||
maxLength?: number
|
||||
precision?: number
|
||||
scale?: number
|
||||
readonly?: boolean
|
||||
importable?: boolean
|
||||
exportable?: boolean
|
||||
sensitive?: boolean
|
||||
masking?: 'name' | 'phone' | 'address' | 'partial'
|
||||
deprecated?: boolean
|
||||
replacementKey?: KbxKnownFieldKey
|
||||
defaultValue?: T
|
||||
lookup?: KbxLookupDefinition
|
||||
helpText?: string
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Generated from contracts/api/kbx.api.json. Do not edit.
|
||||
import type { KbxApiOperationDefinition } from '../api'
|
||||
|
||||
export const kbxApiSourceSha256 = '8a8008b0eca039ef22b703b142dd7fa2efeaf5b14784ba9f3a954f656a1a0c8f' as const
|
||||
export const kbxApiCatalog = {
|
||||
"common.ai.ask": {"id":"common.ai.ask","method":"POST","path":"/api/common/ai/ask","permission":"common.ai.use","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.experiments.assignments": {"id":"common.experiments.assignments","method":"GET","path":"/api/kbx/experiments/assignments","permission":"common.experiment.evaluate","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"common.experiments.overview": {"id":"common.experiments.overview","method":"GET","path":"/api/kbx/experiments","permission":"common.experiment.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"common.experiments.rollback": {"id":"common.experiments.rollback","method":"POST","path":"/api/kbx/experiments/{experimentId}/rollback","permission":"common.experiment.manage","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.experiments.rollout": {"id":"common.experiments.rollout","method":"POST","path":"/api/kbx/experiments/{experimentId}/rollout","permission":"common.experiment.manage","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.externalData.refresh": {"id":"common.externalData.refresh","method":"POST","path":"/api/kbx/external-data/{datasetId}/refresh","permission":"common.external-data.refresh","kind":"command","idempotency":"supported","successStatuses":[202]},
|
||||
"common.externalData.status": {"id":"common.externalData.status","method":"GET","path":"/api/kbx/external-data/status","permission":"common.external-data.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"common.imports.commit": {"id":"common.imports.commit","method":"POST","path":"/api/imports/sessions/{sessionId:guid}/commit","permission":"imports.execute","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.imports.createSession": {"id":"common.imports.createSession","method":"POST","path":"/api/imports/sessions","permission":"imports.execute","kind":"upload","idempotency":"supported","successStatuses":[200],"contentType":"multipart/form-data"},
|
||||
"common.imports.errorWorkbook": {"id":"common.imports.errorWorkbook","method":"GET","path":"/api/imports/sessions/{sessionId:guid}/errors.xlsx","permission":"imports.execute","kind":"query","idempotency":"none","successStatuses":[200],"responseType":"blob"},
|
||||
"common.imports.getSession": {"id":"common.imports.getSession","method":"GET","path":"/api/imports/sessions/{sessionId:guid}","permission":"imports.execute","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"common.imports.saveMapping": {"id":"common.imports.saveMapping","method":"PUT","path":"/api/imports/sessions/{sessionId:guid}/mapping","permission":"imports.execute","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.imports.saveNamedMapping": {"id":"common.imports.saveNamedMapping","method":"POST","path":"/api/imports/sessions/{sessionId:guid}/saved-mappings","permission":"imports.execute","kind":"command","idempotency":"supported","successStatuses":[204]},
|
||||
"common.imports.template": {"id":"common.imports.template","method":"GET","path":"/api/imports/{importType}/template","permission":"imports.execute","kind":"query","idempotency":"none","successStatuses":[200],"responseType":"blob"},
|
||||
"common.imports.validate": {"id":"common.imports.validate","method":"POST","path":"/api/imports/sessions/{sessionId:guid}/validate","permission":"imports.execute","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.integrations.getAttempt": {"id":"common.integrations.getAttempt","method":"GET","path":"/api/integrations/attempts/{attemptId:guid}","permission":"common.integration.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"common.integrations.retryAttempt": {"id":"common.integrations.retryAttempt","method":"POST","path":"/api/integrations/attempts/{attemptId:guid}/retry","permission":"common.integration.retry","kind":"command","idempotency":"required","successStatuses":[200]},
|
||||
"common.operations.claim": {"id":"common.operations.claim","method":"POST","path":"/api/operations/work-items/claim","permission":"common.operations.claim","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.operations.resolve": {"id":"common.operations.resolve","method":"POST","path":"/api/operations/work-items/resolve","permission":"common.operations.resolve","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.operations.retry": {"id":"common.operations.retry","method":"POST","path":"/api/operations/work-items/{id:guid}/retry","permission":"common.operations.retry","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.operations.search": {"id":"common.operations.search","method":"GET","path":"/api/operations/work-items","permission":"common.operations.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"common.reconcile.createExceptions": {"id":"common.reconcile.createExceptions","method":"POST","path":"/api/reconcile/items/create-exceptions","permission":"common.operations.create","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.reconcile.search": {"id":"common.reconcile.search","method":"GET","path":"/api/reconcile/items","permission":"common.reconcile.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"common.runtime.notice": {"id":"common.runtime.notice","method":"GET","path":"/api/kbx/runtime/notice","permission":"common.runtime.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"common.runtime.notificationRead": {"id":"common.runtime.notificationRead","method":"POST","path":"/api/kbx/runtime/notifications/{Id}/read","permission":"common.runtime.read","kind":"command","idempotency":"supported","successStatuses":[204]},
|
||||
"common.runtime.notifications": {"id":"common.runtime.notifications","method":"GET","path":"/api/kbx/runtime/notifications","permission":"common.runtime.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"common.runtime.operations": {"id":"common.runtime.operations","method":"GET","path":"/api/kbx/runtime/operations","permission":"common.runtime.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"common.suggestions.submit": {"id":"common.suggestions.submit","method":"POST","path":"/api/common/suggestions","permission":"common.suggestion.create","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"common.uxTelemetry.ingest": {"id":"common.uxTelemetry.ingest","method":"POST","path":"/api/kbx/ux/events","permission":"common.telemetry.write","kind":"command","idempotency":"none","successStatuses":[204]},
|
||||
"common.uxTelemetry.metrics": {"id":"common.uxTelemetry.metrics","method":"GET","path":"/api/kbx/ux/metrics","permission":"common.ux.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"erp.inventory.history": {"id":"erp.inventory.history","method":"GET","path":"/api/erp/inventory/{itemId}/history","permission":"erp.inventory.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"erp.inventory.locations": {"id":"erp.inventory.locations","method":"GET","path":"/api/erp/inventory/{itemId}/locations","permission":"erp.inventory.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"erp.inventory.search": {"id":"erp.inventory.search","method":"GET","path":"/api/erp/inventory","permission":"erp.inventory.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"erp.itemPrices.bulkSave": {"id":"erp.itemPrices.bulkSave","method":"POST","path":"/api/erp/item-prices/bulk","permission":"erp.item.price.write","kind":"command","idempotency":"required","successStatuses":[200]},
|
||||
"erp.items.get": {"id":"erp.items.get","method":"GET","path":"/api/erp/items/{id}","permission":"erp.item.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"erp.items.search": {"id":"erp.items.search","method":"GET","path":"/api/erp/items","permission":"erp.item.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"lookup.customers.resolveByCode": {"id":"lookup.customers.resolveByCode","method":"GET","path":"/api/lookups/customers/by-code/{code}","permission":"oms.order.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"lookup.customers.resolveById": {"id":"lookup.customers.resolveById","method":"GET","path":"/api/lookups/customers/{id}","permission":"oms.order.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"lookup.customers.search": {"id":"lookup.customers.search","method":"GET","path":"/api/lookups/customers","permission":"oms.order.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"lookup.items.resolveByCode": {"id":"lookup.items.resolveByCode","method":"GET","path":"/api/lookups/items/by-code/{code}","permission":"erp.item.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"lookup.items.resolveById": {"id":"lookup.items.resolveById","method":"GET","path":"/api/lookups/items/{id}","permission":"erp.item.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"lookup.items.search": {"id":"lookup.items.search","method":"GET","path":"/api/lookups/items","permission":"erp.item.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"lookup.warehouses.resolveByCode": {"id":"lookup.warehouses.resolveByCode","method":"GET","path":"/api/lookups/warehouses/by-code/{code}","permission":"oms.order.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"lookup.warehouses.resolveById": {"id":"lookup.warehouses.resolveById","method":"GET","path":"/api/lookups/warehouses/{id}","permission":"oms.order.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"lookup.warehouses.search": {"id":"lookup.warehouses.search","method":"GET","path":"/api/lookups/warehouses","permission":"oms.order.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"oms.claims.approve": {"id":"oms.claims.approve","method":"POST","path":"/api/oms/claims/{id:guid}/approve","permission":"oms.claim.approve","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"oms.claims.complete": {"id":"oms.claims.complete","method":"POST","path":"/api/oms/claims/{id:guid}/complete","permission":"oms.claim.process","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"oms.claims.hold": {"id":"oms.claims.hold","method":"POST","path":"/api/oms/claims/{id:guid}/hold","permission":"oms.claim.hold","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"oms.claims.search": {"id":"oms.claims.search","method":"GET","path":"/api/oms/claims","permission":"oms.claim.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"oms.claims.start": {"id":"oms.claims.start","method":"POST","path":"/api/oms/claims/{id:guid}/start","permission":"oms.claim.process","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"oms.orders.register": {"id":"oms.orders.register","method":"POST","path":"/api/oms/orders/register","permission":"oms.order.create","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"oms.orders.search": {"id":"oms.orders.search","method":"GET","path":"/api/oms/orders","permission":"oms.order.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"oms.orders.ship": {"id":"oms.orders.ship","method":"POST","path":"/api/oms/orders/ship","permission":"oms.order.ship","kind":"command","idempotency":"required","successStatuses":[200]},
|
||||
"wms.picking.getTask": {"id":"wms.picking.getTask","method":"GET","path":"/api/wms/picking/tasks/{taskId:guid}","permission":"wms.picking.execute","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"wms.picking.reportException": {"id":"wms.picking.reportException","method":"POST","path":"/api/wms/picking/tasks/{taskId:guid}/exceptions","permission":"wms.picking.execute","kind":"command","idempotency":"required","successStatuses":[200]},
|
||||
"wms.picking.scan": {"id":"wms.picking.scan","method":"POST","path":"/api/wms/picking/tasks/{taskId:guid}/scan","permission":"wms.picking.execute","kind":"command","idempotency":"required","successStatuses":[200,422]},
|
||||
"wms.picking.setQuantity": {"id":"wms.picking.setQuantity","method":"POST","path":"/api/wms/picking/tasks/{taskId:guid}/quantity","permission":"wms.picking.execute","kind":"command","idempotency":"required","successStatuses":[200]},
|
||||
"wms.picking.start": {"id":"wms.picking.start","method":"POST","path":"/api/wms/picking/tasks/{taskId:guid}/start","permission":"wms.picking.execute","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
"erp.items.create": {"id":"erp.items.create","method":"POST","path":"/api/erp/items","permission":"erp.item.create","kind":"command","idempotency":"none","successStatuses":[200]},
|
||||
"erp.items.update": {"id":"erp.items.update","method":"PUT","path":"/api/erp/items/{id}","permission":"erp.item.write","kind":"command","idempotency":"none","successStatuses":[200]},
|
||||
"erp.items.deactivate": {"id":"erp.items.deactivate","method":"POST","path":"/api/erp/items/{id}/deactivate","permission":"erp.item.write","kind":"command","idempotency":"none","successStatuses":[200]},
|
||||
"erp.items.audit": {"id":"erp.items.audit","method":"GET","path":"/api/erp/items/{id}/audit","permission":"erp.item.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"oms.orders.get": {"id":"oms.orders.get","method":"GET","path":"/api/oms/orders/{id}","permission":"oms.order.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"oms.orders.confirm": {"id":"oms.orders.confirm","method":"POST","path":"/api/oms/orders/{id}/confirm","permission":"oms.order.confirm","kind":"command","idempotency":"required","successStatuses":[200]},
|
||||
"oms.orders.audit": {"id":"oms.orders.audit","method":"GET","path":"/api/oms/orders/{id}/audit","permission":"oms.order.read","kind":"query","idempotency":"none","successStatuses":[200]},
|
||||
"oms.orders.update": {"id":"oms.orders.update","method":"PUT","path":"/api/oms/orders/{id}","permission":"oms.order.write","kind":"command","idempotency":"supported","successStatuses":[200]},
|
||||
} as const satisfies Record<string, KbxApiOperationDefinition>
|
||||
|
||||
export type KbxApiOperationId = keyof typeof kbxApiCatalog
|
||||
export type KbxApiOperation = (typeof kbxApiCatalog)[KbxApiOperationId]
|
||||
+506
@@ -0,0 +1,506 @@
|
||||
// generated from contracts/configuration/kbx.configuration.json; do not edit.
|
||||
import type { KbxConfigurationSettingDefinition, KbxEnvironmentProfileDefinition } from '../configuration'
|
||||
export const kbxConfigurationSourceSha256='e09186d626b034a524b7cdf78f1e4bb6adbc112975b3baf4fd6194b1c1abd771' as const
|
||||
export const kbxConfigurationCatalog={
|
||||
"Kbx:Runtime:Environment": {
|
||||
"key": "Kbx:Runtime:Environment",
|
||||
"env": "KBX__Runtime__Environment",
|
||||
"category": "runtime",
|
||||
"type": "enum",
|
||||
"allowedValues": [
|
||||
"Development",
|
||||
"Test",
|
||||
"Staging",
|
||||
"Production"
|
||||
],
|
||||
"default": "Development",
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": [
|
||||
"Development",
|
||||
"Test",
|
||||
"Staging",
|
||||
"Production"
|
||||
]
|
||||
},
|
||||
"Kbx:Runtime:ReadOnly": {
|
||||
"key": "Kbx:Runtime:ReadOnly",
|
||||
"env": "KBX__Runtime__ReadOnly",
|
||||
"category": "runtime",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"secret": false,
|
||||
"restartRequired": false,
|
||||
"requiredIn": []
|
||||
},
|
||||
"ConnectionStrings:Main": {
|
||||
"key": "ConnectionStrings:Main",
|
||||
"env": "ConnectionStrings__Main",
|
||||
"category": "database",
|
||||
"type": "connection-string",
|
||||
"secret": true,
|
||||
"restartRequired": true,
|
||||
"requiredIn": [
|
||||
"Development",
|
||||
"Test",
|
||||
"Staging",
|
||||
"Production"
|
||||
],
|
||||
"allowedSources": [
|
||||
"environment",
|
||||
"secret-store",
|
||||
"user-secrets"
|
||||
]
|
||||
},
|
||||
"Kbx:Database:MigrationsMode": {
|
||||
"key": "Kbx:Database:MigrationsMode",
|
||||
"env": "KBX__Database__MigrationsMode",
|
||||
"category": "database",
|
||||
"type": "enum",
|
||||
"allowedValues": [
|
||||
"validate",
|
||||
"startup-apply",
|
||||
"predeploy"
|
||||
],
|
||||
"default": "validate",
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": [
|
||||
"Development",
|
||||
"Test",
|
||||
"Staging",
|
||||
"Production"
|
||||
]
|
||||
},
|
||||
"Kbx:Database:CommandTimeoutSeconds": {
|
||||
"key": "Kbx:Database:CommandTimeoutSeconds",
|
||||
"env": "KBX__Database__CommandTimeoutSeconds",
|
||||
"category": "database",
|
||||
"type": "integer",
|
||||
"default": 30,
|
||||
"minimum": 1,
|
||||
"maximum": 300,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Hangfire:Enabled": {
|
||||
"key": "Kbx:Hangfire:Enabled",
|
||||
"env": "KBX__Hangfire__Enabled",
|
||||
"category": "background-jobs",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Hangfire:WorkerCount": {
|
||||
"key": "Kbx:Hangfire:WorkerCount",
|
||||
"env": "KBX__Hangfire__WorkerCount",
|
||||
"category": "background-jobs",
|
||||
"type": "integer",
|
||||
"default": 4,
|
||||
"minimum": 1,
|
||||
"maximum": 64,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:SignalR:Enabled": {
|
||||
"key": "Kbx:SignalR:Enabled",
|
||||
"env": "KBX__SignalR__Enabled",
|
||||
"category": "realtime",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Outbox:DispatcherEnabled": {
|
||||
"key": "Kbx:Outbox:DispatcherEnabled",
|
||||
"env": "KBX__Outbox__DispatcherEnabled",
|
||||
"category": "messaging",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Inbox:CleanupEnabled": {
|
||||
"key": "Kbx:Inbox:CleanupEnabled",
|
||||
"env": "KBX__Inbox__CleanupEnabled",
|
||||
"category": "messaging",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Integration:DispatcherEnabled": {
|
||||
"key": "Kbx:Integration:DispatcherEnabled",
|
||||
"env": "KBX__Integration__DispatcherEnabled",
|
||||
"category": "integration",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:ExternalData:RefreshEnabled": {
|
||||
"key": "Kbx:ExternalData:RefreshEnabled",
|
||||
"env": "KBX__ExternalData__RefreshEnabled",
|
||||
"category": "external-data",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:ExternalData:ObservationRetentionEnabled": {
|
||||
"key": "Kbx:ExternalData:ObservationRetentionEnabled",
|
||||
"env": "KBX__ExternalData__ObservationRetentionEnabled",
|
||||
"category": "external-data",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Experiments:Enabled": {
|
||||
"key": "Kbx:Experiments:Enabled",
|
||||
"env": "KBX__Experiments__Enabled",
|
||||
"category": "experiments",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": false,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Logging:MinimumLevel": {
|
||||
"key": "Kbx:Logging:MinimumLevel",
|
||||
"env": "KBX__Logging__MinimumLevel",
|
||||
"category": "logging",
|
||||
"type": "enum",
|
||||
"allowedValues": [
|
||||
"Debug",
|
||||
"Information",
|
||||
"Warning",
|
||||
"Error"
|
||||
],
|
||||
"default": "Information",
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Logging:JsonConsoleEnabled": {
|
||||
"key": "Kbx:Logging:JsonConsoleEnabled",
|
||||
"env": "KBX__Logging__JsonConsoleEnabled",
|
||||
"category": "logging",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Telemetry:Enabled": {
|
||||
"key": "Kbx:Telemetry:Enabled",
|
||||
"env": "KBX__Telemetry__Enabled",
|
||||
"category": "observability",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Telemetry:OtlpEndpoint": {
|
||||
"key": "Kbx:Telemetry:OtlpEndpoint",
|
||||
"env": "KBX__Telemetry__OtlpEndpoint",
|
||||
"category": "observability",
|
||||
"type": "uri",
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Telegram:Enabled": {
|
||||
"key": "Kbx:Telegram:Enabled",
|
||||
"env": "KBX__Telegram__Enabled",
|
||||
"category": "alerting",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Telegram:BotToken": {
|
||||
"key": "Kbx:Telegram:BotToken",
|
||||
"env": "KBX__Telegram__BotToken",
|
||||
"category": "alerting",
|
||||
"type": "string",
|
||||
"secret": true,
|
||||
"restartRequired": true,
|
||||
"requiredWhen": {
|
||||
"key": "Kbx:Telegram:Enabled",
|
||||
"equals": true
|
||||
},
|
||||
"allowedSources": [
|
||||
"environment",
|
||||
"secret-store",
|
||||
"user-secrets"
|
||||
]
|
||||
},
|
||||
"Kbx:Telegram:ChatId": {
|
||||
"key": "Kbx:Telegram:ChatId",
|
||||
"env": "KBX__Telegram__ChatId",
|
||||
"category": "alerting",
|
||||
"type": "string",
|
||||
"secret": true,
|
||||
"restartRequired": true,
|
||||
"requiredWhen": {
|
||||
"key": "Kbx:Telegram:Enabled",
|
||||
"equals": true
|
||||
},
|
||||
"allowedSources": [
|
||||
"environment",
|
||||
"secret-store",
|
||||
"user-secrets"
|
||||
]
|
||||
},
|
||||
"ExternalProviders:Krx:Enabled": {
|
||||
"key": "ExternalProviders:Krx:Enabled",
|
||||
"env": "ExternalProviders__Krx__Enabled",
|
||||
"category": "provider",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"ExternalProviders:Krx:AuthKey": {
|
||||
"key": "ExternalProviders:Krx:AuthKey",
|
||||
"env": "ExternalProviders__Krx__AuthKey",
|
||||
"category": "provider",
|
||||
"type": "string",
|
||||
"secret": true,
|
||||
"restartRequired": true,
|
||||
"requiredWhen": {
|
||||
"key": "ExternalProviders:Krx:Enabled",
|
||||
"equals": true
|
||||
},
|
||||
"allowedSources": [
|
||||
"environment",
|
||||
"secret-store",
|
||||
"user-secrets"
|
||||
]
|
||||
},
|
||||
"ExternalProviders:OpenDart:Enabled": {
|
||||
"key": "ExternalProviders:OpenDart:Enabled",
|
||||
"env": "ExternalProviders__OpenDart__Enabled",
|
||||
"category": "provider",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"ExternalProviders:OpenDart:ApiKey": {
|
||||
"key": "ExternalProviders:OpenDart:ApiKey",
|
||||
"env": "ExternalProviders__OpenDart__ApiKey",
|
||||
"category": "provider",
|
||||
"type": "string",
|
||||
"secret": true,
|
||||
"restartRequired": true,
|
||||
"requiredWhen": {
|
||||
"key": "ExternalProviders:OpenDart:Enabled",
|
||||
"equals": true
|
||||
},
|
||||
"allowedSources": [
|
||||
"environment",
|
||||
"secret-store",
|
||||
"user-secrets"
|
||||
]
|
||||
},
|
||||
"ExternalProviders:Kis:Enabled": {
|
||||
"key": "ExternalProviders:Kis:Enabled",
|
||||
"env": "ExternalProviders__Kis__Enabled",
|
||||
"category": "provider",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"ExternalProviders:Kis:Environment": {
|
||||
"key": "ExternalProviders:Kis:Environment",
|
||||
"env": "ExternalProviders__Kis__Environment",
|
||||
"category": "provider",
|
||||
"type": "enum",
|
||||
"allowedValues": [
|
||||
"sandbox",
|
||||
"production"
|
||||
],
|
||||
"default": "sandbox",
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredWhen": {
|
||||
"key": "ExternalProviders:Kis:Enabled",
|
||||
"equals": true
|
||||
}
|
||||
},
|
||||
"ExternalProviders:Kis:AppKey": {
|
||||
"key": "ExternalProviders:Kis:AppKey",
|
||||
"env": "ExternalProviders__Kis__AppKey",
|
||||
"category": "provider",
|
||||
"type": "string",
|
||||
"secret": true,
|
||||
"restartRequired": true,
|
||||
"requiredWhen": {
|
||||
"key": "ExternalProviders:Kis:Enabled",
|
||||
"equals": true
|
||||
},
|
||||
"allowedSources": [
|
||||
"environment",
|
||||
"secret-store",
|
||||
"user-secrets"
|
||||
]
|
||||
},
|
||||
"ExternalProviders:Kis:AppSecret": {
|
||||
"key": "ExternalProviders:Kis:AppSecret",
|
||||
"env": "ExternalProviders__Kis__AppSecret",
|
||||
"category": "provider",
|
||||
"type": "string",
|
||||
"secret": true,
|
||||
"restartRequired": true,
|
||||
"requiredWhen": {
|
||||
"key": "ExternalProviders:Kis:Enabled",
|
||||
"equals": true
|
||||
},
|
||||
"allowedSources": [
|
||||
"environment",
|
||||
"secret-store",
|
||||
"user-secrets"
|
||||
]
|
||||
},
|
||||
"Kbx:Security:RequireHttps": {
|
||||
"key": "Kbx:Security:RequireHttps",
|
||||
"env": "KBX__Security__RequireHttps",
|
||||
"category": "security",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Health:ReadinessEnabled": {
|
||||
"key": "Kbx:Health:ReadinessEnabled",
|
||||
"env": "KBX__Health__ReadinessEnabled",
|
||||
"category": "runtime",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Import:MaxUploadBytes": {
|
||||
"key": "Kbx:Import:MaxUploadBytes",
|
||||
"env": "KBX__Import__MaxUploadBytes",
|
||||
"category": "import",
|
||||
"type": "integer",
|
||||
"default": 52428800,
|
||||
"minimum": 1048576,
|
||||
"maximum": 209715200,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
},
|
||||
"Kbx:Import:MaxRows": {
|
||||
"key": "Kbx:Import:MaxRows",
|
||||
"env": "KBX__Import__MaxRows",
|
||||
"category": "import",
|
||||
"type": "integer",
|
||||
"default": 100000,
|
||||
"minimum": 1,
|
||||
"maximum": 1000000,
|
||||
"secret": false,
|
||||
"restartRequired": true,
|
||||
"requiredIn": []
|
||||
}
|
||||
} as const satisfies Record<string,KbxConfigurationSettingDefinition>
|
||||
export const kbxEnvironmentProfiles={
|
||||
"Development": {
|
||||
"id": "Development",
|
||||
"artifactPromotion": false,
|
||||
"secretSources": [
|
||||
"user-secrets",
|
||||
"environment"
|
||||
],
|
||||
"migrationStrategy": "startup-apply-allowed",
|
||||
"providerNetwork": "opt-in",
|
||||
"requireHttps": false,
|
||||
"providerEndpointOverrideAllowed": true,
|
||||
"requiredGates": [
|
||||
"static-governance"
|
||||
]
|
||||
},
|
||||
"Test": {
|
||||
"id": "Test",
|
||||
"artifactPromotion": false,
|
||||
"secretSources": [
|
||||
"environment"
|
||||
],
|
||||
"migrationStrategy": "ephemeral-apply",
|
||||
"providerNetwork": "forbidden",
|
||||
"requireHttps": false,
|
||||
"providerEndpointOverrideAllowed": true,
|
||||
"requiredGates": [
|
||||
"static-governance",
|
||||
"build",
|
||||
"unit",
|
||||
"integration",
|
||||
"scenario"
|
||||
]
|
||||
},
|
||||
"Staging": {
|
||||
"id": "Staging",
|
||||
"artifactPromotion": true,
|
||||
"secretSources": [
|
||||
"secret-store",
|
||||
"environment"
|
||||
],
|
||||
"migrationStrategy": "predeploy",
|
||||
"providerNetwork": "opt-in",
|
||||
"requireHttps": true,
|
||||
"providerEndpointOverrideAllowed": false,
|
||||
"requiredGates": [
|
||||
"static-governance",
|
||||
"build",
|
||||
"unit",
|
||||
"integration",
|
||||
"scenario",
|
||||
"migration-dry-run"
|
||||
]
|
||||
},
|
||||
"Production": {
|
||||
"id": "Production",
|
||||
"artifactPromotion": true,
|
||||
"secretSources": [
|
||||
"secret-store",
|
||||
"environment"
|
||||
],
|
||||
"migrationStrategy": "predeploy",
|
||||
"providerNetwork": "opt-in",
|
||||
"requireHttps": true,
|
||||
"providerEndpointOverrideAllowed": false,
|
||||
"requiredGates": [
|
||||
"static-governance",
|
||||
"build",
|
||||
"unit",
|
||||
"integration",
|
||||
"scenario",
|
||||
"migration-dry-run",
|
||||
"configuration-validation",
|
||||
"release-governance"
|
||||
]
|
||||
}
|
||||
} as const satisfies Record<string,KbxEnvironmentProfileDefinition>
|
||||
export type KbxConfigurationKey=keyof typeof kbxConfigurationCatalog
|
||||
export type KbxEnvironmentProfile=keyof typeof kbxEnvironmentProfiles
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// generated from contracts/experiments/kbx.experiments.json; do not edit.
|
||||
export const kbxFeatureFlags = {
|
||||
"oms.order-list.exception-summary-v2": {
|
||||
"id": "oms.order-list.exception-summary-v2",
|
||||
"screenId": "OMS-ORD-001",
|
||||
"surface": "information-emphasis",
|
||||
"description": "기존 주문 Quick Filter를 이동시키지 않고 확인 필요 예외 요약을 보조적으로 노출하는 되돌릴 수 있는 UX 변경",
|
||||
"defaultVariant": "control",
|
||||
"killSwitch": true,
|
||||
"owner": "KBX"
|
||||
}
|
||||
} as const
|
||||
export const kbxExperiments = {
|
||||
"exp.oms.order-list.exception-summary-v2": {
|
||||
"id": "exp.oms.order-list.exception-summary-v2",
|
||||
"flagId": "oms.order-list.exception-summary-v2",
|
||||
"screenId": "OMS-ORD-001",
|
||||
"state": "draft",
|
||||
"rolloutPercent": 0,
|
||||
"minExposurePerVariant": 200,
|
||||
"variants": [
|
||||
{
|
||||
"key": "control",
|
||||
"weight": 50
|
||||
},
|
||||
{
|
||||
"key": "exception-summary",
|
||||
"weight": 50
|
||||
}
|
||||
],
|
||||
"primaryMetric": {
|
||||
"key": "semantic_interactions_per_task",
|
||||
"direction": "lower",
|
||||
"minimumImprovementPercent": 10
|
||||
},
|
||||
"guardrails": [
|
||||
{
|
||||
"key": "task_completion_time_ms",
|
||||
"statistic": "p95",
|
||||
"maxRegressionPercent": 20
|
||||
},
|
||||
{
|
||||
"key": "validation_failure_rate",
|
||||
"statistic": "rate",
|
||||
"maxAbsoluteRegressionPercentagePoints": 2
|
||||
}
|
||||
],
|
||||
"globalGuardrails": [
|
||||
{
|
||||
"key": "manual_intervention_rate",
|
||||
"maxAbsoluteRegressionPercentagePoints": 0.5
|
||||
}
|
||||
],
|
||||
"notes": "Reference experiment only. v17 ships at draft/0%; rollout requires an explicit runtime decision and can be killed immediately."
|
||||
}
|
||||
} as const
|
||||
export type KbxFeatureFlagId = keyof typeof kbxFeatureFlags
|
||||
export type KbxExperimentId = keyof typeof kbxExperiments
|
||||
export const kbxExperimentSourceSha256 = '2510a2927bab297858e09e75c8af9bb766d91b92cc0daf99433f6377d399fbf9' as const
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
// generated from contracts/external-data/kbx.external-data.json; do not edit.
|
||||
import type { KbxExternalDataDatasetDefinition } from '../externalData'
|
||||
export const kbxExternalDataSourceSha256='da54ff739c6dc5ed6f9390d1fc8a8e138060d7cf19531a80cc91e421d62954a4' as const
|
||||
export const kbxExternalDataCatalog={
|
||||
"dataset.opendart.company-profile": {
|
||||
"id": "dataset.opendart.company-profile",
|
||||
"providerId": "provider.opendart",
|
||||
"providerOperationId": "opendart.company",
|
||||
"canonicalType": "company-profile",
|
||||
"normalizer": "OpenDartCompanyProfileNormalizer",
|
||||
"normalizerVersion": "1.0.0",
|
||||
"cacheKeyFields": [
|
||||
"corpCode"
|
||||
],
|
||||
"freshness": {
|
||||
"mode": "stale-while-revalidate",
|
||||
"freshForSeconds": 86400,
|
||||
"maxStaleSeconds": 604800,
|
||||
"backgroundRefresh": true
|
||||
},
|
||||
"snapshot": {
|
||||
"rawRetention": "hash-only",
|
||||
"normalizedRetentionDays": 365
|
||||
},
|
||||
"ui": {
|
||||
"sourceLabel": "OPENDART",
|
||||
"showProviderObservedAt": false,
|
||||
"showReceivedAt": true
|
||||
}
|
||||
},
|
||||
"dataset.opendart.disclosures": {
|
||||
"id": "dataset.opendart.disclosures",
|
||||
"providerId": "provider.opendart",
|
||||
"providerOperationId": "opendart.disclosures",
|
||||
"canonicalType": "disclosure-list",
|
||||
"normalizer": "OpenDartDisclosureListNormalizer",
|
||||
"normalizerVersion": "1.0.0",
|
||||
"cacheKeyFields": [
|
||||
"corpCode",
|
||||
"beginDate",
|
||||
"endDate",
|
||||
"pageNo",
|
||||
"pageCount"
|
||||
],
|
||||
"freshness": {
|
||||
"mode": "stale-while-revalidate",
|
||||
"freshForSeconds": 300,
|
||||
"maxStaleSeconds": 3600,
|
||||
"backgroundRefresh": true
|
||||
},
|
||||
"snapshot": {
|
||||
"rawRetention": "hash-only",
|
||||
"normalizedRetentionDays": 90
|
||||
},
|
||||
"ui": {
|
||||
"sourceLabel": "OPENDART",
|
||||
"showProviderObservedAt": false,
|
||||
"showReceivedAt": true
|
||||
}
|
||||
},
|
||||
"dataset.kis.domestic-stock.current-price": {
|
||||
"id": "dataset.kis.domestic-stock.current-price",
|
||||
"providerId": "provider.kis.market-data",
|
||||
"providerOperationId": "kis.domestic-stock.current-price",
|
||||
"canonicalType": "market-price",
|
||||
"normalizer": "KisCurrentPriceNormalizer",
|
||||
"normalizerVersion": "1.0.0",
|
||||
"cacheKeyFields": [
|
||||
"marketDivisionCode",
|
||||
"stockCode",
|
||||
"environment"
|
||||
],
|
||||
"freshness": {
|
||||
"mode": "strict",
|
||||
"freshForSeconds": 3,
|
||||
"maxStaleSeconds": 0,
|
||||
"backgroundRefresh": false
|
||||
},
|
||||
"snapshot": {
|
||||
"rawRetention": "hash-only",
|
||||
"normalizedRetentionDays": 7
|
||||
},
|
||||
"ui": {
|
||||
"sourceLabel": "KIS",
|
||||
"showProviderObservedAt": false,
|
||||
"showReceivedAt": true
|
||||
}
|
||||
},
|
||||
"dataset.krx.approved-service": {
|
||||
"id": "dataset.krx.approved-service",
|
||||
"providerId": "provider.krx.openapi",
|
||||
"providerOperationId": "krx.approved-service.invoke",
|
||||
"canonicalType": "provider-defined",
|
||||
"normalizer": "registered-per-approved-service",
|
||||
"normalizerVersion": "provider-defined",
|
||||
"cacheKeyFields": [
|
||||
"serviceId",
|
||||
"querySignature"
|
||||
],
|
||||
"freshness": {
|
||||
"mode": "provider-defined",
|
||||
"freshForSeconds": null,
|
||||
"maxStaleSeconds": null,
|
||||
"backgroundRefresh": false,
|
||||
"requireExplicitServicePolicy": true
|
||||
},
|
||||
"snapshot": {
|
||||
"rawRetention": "hash-only",
|
||||
"normalizedRetentionDays": 30
|
||||
},
|
||||
"ui": {
|
||||
"sourceLabel": "KRX",
|
||||
"showProviderObservedAt": false,
|
||||
"showReceivedAt": true
|
||||
}
|
||||
}
|
||||
} as const satisfies Record<string,KbxExternalDataDatasetDefinition>
|
||||
export type KbxExternalDataDatasetId=keyof typeof kbxExternalDataCatalog
|
||||
@@ -0,0 +1,66 @@
|
||||
// GENERATED FILE. DO NOT EDIT.
|
||||
// Source: contracts/fields/kbx.fields.json
|
||||
// Source SHA256: f76e073cd8052e9fddb25cc73322686c889822a22fab712ff1a25bef29b32e3c
|
||||
|
||||
export const kbxFieldDictionaryVersion = "1.1.0" as const
|
||||
|
||||
export const kbxFieldCatalog = {
|
||||
"address1": {"key":"address1","label":"주소","aliases":["기본주소","배송주소","Address1"],"dataType":"text","required":true,"maxLength":500,"importable":true,"exportable":true,"sensitive":true,"masking":"address"},
|
||||
"address2": {"key":"address2","label":"상세주소","aliases":["주소2","Address2"],"dataType":"text","maxLength":500,"importable":true,"exportable":true,"sensitive":true,"masking":"address"},
|
||||
"allocatedQty": {"key":"allocatedQty","label":"할당수량","aliases":["AllocatedQty"],"dataType":"quantity","precision":18,"scale":4,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"amount": {"key":"amount","label":"금액","aliases":["Amount","주문금액"],"dataType":"money","precision":18,"scale":2,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"availableQty": {"key":"availableQty","label":"가용재고","aliases":["AvailableQty","출고가능수량"],"dataType":"quantity","precision":18,"scale":4,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"barcode": {"key":"barcode","label":"바코드","aliases":["Barcode","EAN","JAN"],"dataType":"code","maxLength":100,"lookupEntity":"item","importable":true,"exportable":true,"sensitive":false},
|
||||
"channelId": {"key":"channelId","label":"판매채널ID","aliases":["ChannelId"],"dataType":"lookup","lookupEntity":"salesChannel","readonly":true,"importable":false,"exportable":false,"sensitive":false},
|
||||
"channelName": {"key":"channelName","label":"판매채널","aliases":["ChannelName","채널"],"dataType":"text","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"createdAt": {"key":"createdAt","label":"등록일시","aliases":["CreatedAt"],"dataType":"datetime","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"createdBy": {"key":"createdBy","label":"등록자","aliases":["CreatedBy"],"dataType":"text","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"customerCode": {"key":"customerCode","label":"거래처코드","aliases":["거래처","업체코드","CustomerCode"],"dataType":"code","required":true,"maxLength":50,"lookupEntity":"customer","importable":true,"exportable":true,"sensitive":false},
|
||||
"customerId": {"key":"customerId","label":"거래처ID","aliases":["CustomerId"],"dataType":"lookup","lookupEntity":"customer","readonly":true,"importable":false,"exportable":false,"sensitive":false},
|
||||
"customerName": {"key":"customerName","label":"거래처명","aliases":["CustomerName","업체명"],"dataType":"text","maxLength":200,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"damagedQty": {"key":"damagedQty","label":"불량수량","aliases":["DamagedQty"],"dataType":"quantity","precision":18,"scale":4,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"effectiveDate": {"key":"effectiveDate","label":"적용일","aliases":["EffectiveDate","시작일","적용시작일"],"dataType":"date","required":true,"importable":true,"exportable":true,"sensitive":false},
|
||||
"exceptionCount": {"key":"exceptionCount","label":"예외건수","aliases":["ExceptionCount","오류건수"],"dataType":"integer","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"expiryDate": {"key":"expiryDate","label":"유통기한","aliases":["ExpiryDate","ExpirationDate"],"dataType":"date","importable":true,"exportable":true,"sensitive":false},
|
||||
"holdQty": {"key":"holdQty","label":"보류수량","aliases":["HoldQty"],"dataType":"quantity","precision":18,"scale":4,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"itemCode": {"key":"itemCode","label":"품목코드","aliases":["상품코드","SKU","ItemCode"],"dataType":"code","required":true,"maxLength":80,"lookupEntity":"item","importable":true,"exportable":true,"sensitive":false},
|
||||
"itemId": {"key":"itemId","label":"품목ID","aliases":["ItemId"],"dataType":"lookup","lookupEntity":"item","readonly":true,"importable":false,"exportable":false,"sensitive":false},
|
||||
"itemName": {"key":"itemName","label":"품목명","aliases":["상품명","ItemName"],"dataType":"text","maxLength":300,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"itemSummary": {"key":"itemSummary","label":"대표상품","aliases":["ItemSummary"],"dataType":"text","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"locationCode": {"key":"locationCode","label":"로케이션","aliases":["Location","LocationCode","위치"],"dataType":"code","maxLength":80,"lookupEntity":"location","importable":true,"exportable":true,"sensitive":false},
|
||||
"locationId": {"key":"locationId","label":"로케이션ID","aliases":["LocationId"],"dataType":"lookup","lookupEntity":"location","readonly":true,"importable":false,"exportable":false,"sensitive":false},
|
||||
"lotNo": {"key":"lotNo","label":"LOT","aliases":["LotNo","LOT번호"],"dataType":"code","maxLength":100,"importable":true,"exportable":true,"sensitive":false},
|
||||
"occurredAt": {"key":"occurredAt","label":"발생시각","aliases":["OccurredAt"],"dataType":"datetime","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"onHandQty": {"key":"onHandQty","label":"현재고","aliases":["OnHandQty","장부재고"],"dataType":"quantity","precision":18,"scale":4,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"orderDate": {"key":"orderDate","label":"주문일","aliases":["주문일자","OrderDate"],"dataType":"date","required":true,"importable":true,"exportable":true,"sensitive":false},
|
||||
"orderedAt": {"key":"orderedAt","label":"주문일시","aliases":["OrderedAt","주문시간"],"dataType":"datetime","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"orderId": {"key":"orderId","label":"주문ID","aliases":["OrderId"],"dataType":"code","readonly":true,"importable":false,"exportable":false,"sensitive":false},
|
||||
"orderNo": {"key":"orderNo","label":"주문번호","aliases":["OrderNo","주문ID"],"dataType":"code","required":true,"maxLength":50,"importable":true,"exportable":true,"sensitive":false},
|
||||
"orderQty": {"key":"orderQty","label":"주문수량","aliases":["주문수량","수량","Qty","OrderQty"],"dataType":"quantity","precision":18,"scale":4,"importable":true,"exportable":true,"sensitive":false,"required":true},
|
||||
"ownerName": {"key":"ownerName","label":"담당자","aliases":["OwnerName","담당"],"dataType":"text","maxLength":100,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"phone": {"key":"phone","label":"연락처","aliases":["휴대폰","전화번호","Phone"],"dataType":"text","required":true,"maxLength":50,"importable":true,"exportable":true,"sensitive":true,"masking":"phone"},
|
||||
"pickedQty": {"key":"pickedQty","label":"피킹수량","aliases":["PickedQty"],"dataType":"quantity","precision":18,"scale":4,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"postalCode": {"key":"postalCode","label":"우편번호","aliases":["ZipCode","PostalCode"],"dataType":"text","maxLength":20,"importable":true,"exportable":true,"sensitive":true,"masking":"address"},
|
||||
"quantity": {"key":"quantity","label":"수량","aliases":["Qty"],"dataType":"quantity","precision":18,"scale":4,"importable":false,"exportable":false,"sensitive":false},
|
||||
"receiverName": {"key":"receiverName","label":"수취인","aliases":["받는분","수령인","ReceiverName"],"dataType":"text","required":true,"maxLength":100,"importable":true,"exportable":true,"sensitive":true,"masking":"name"},
|
||||
"referenceNo": {"key":"referenceNo","label":"참조번호","aliases":["ReferenceNo"],"dataType":"code","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"remark": {"key":"remark","label":"비고","aliases":["메모","배송메모","Remark"],"dataType":"text","maxLength":500,"importable":true,"exportable":true,"sensitive":false},
|
||||
"shippedQty": {"key":"shippedQty","label":"출고수량","aliases":["ShippedQty"],"dataType":"quantity","precision":18,"scale":4,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"specification": {"key":"specification","label":"규격","aliases":["Specification","Spec"],"dataType":"text","maxLength":200,"importable":true,"exportable":true,"sensitive":false},
|
||||
"status": {"key":"status","label":"상태","aliases":["Status"],"dataType":"status","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"totalQty": {"key":"totalQty","label":"총수량","aliases":["TotalQty"],"dataType":"quantity","precision":18,"scale":4,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"unitPrice": {"key":"unitPrice","label":"단가","aliases":["판매단가","UnitPrice"],"dataType":"money","precision":18,"scale":4,"importable":true,"exportable":true,"sensitive":false},
|
||||
"updatedAt": {"key":"updatedAt","label":"수정일시","aliases":["UpdatedAt"],"dataType":"datetime","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"updatedBy": {"key":"updatedBy","label":"수정자","aliases":["UpdatedBy"],"dataType":"text","readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
"version": {"key":"version","label":"버전","aliases":["Version","RowVersion"],"dataType":"integer","readonly":true,"importable":false,"exportable":false,"sensitive":false},
|
||||
"warehouseCode": {"key":"warehouseCode","label":"창고코드","aliases":["창고","창고코드","출고창고","WarehouseCode"],"dataType":"code","required":true,"maxLength":50,"lookupEntity":"warehouse","importable":true,"exportable":true,"sensitive":false},
|
||||
"warehouseId": {"key":"warehouseId","label":"창고ID","aliases":["WarehouseId"],"dataType":"lookup","lookupEntity":"warehouse","readonly":true,"importable":false,"exportable":false,"sensitive":false},
|
||||
"warehouseName": {"key":"warehouseName","label":"창고명","aliases":["WarehouseName"],"dataType":"text","maxLength":200,"readonly":true,"importable":false,"exportable":true,"sensitive":false},
|
||||
} as const
|
||||
|
||||
export type KbxKnownFieldKey = keyof typeof kbxFieldCatalog
|
||||
export type KbxKnownFieldDefinition = (typeof kbxFieldCatalog)[KbxKnownFieldKey]
|
||||
|
||||
export function getKbxField<K extends KbxKnownFieldKey>(key: K): (typeof kbxFieldCatalog)[K] {
|
||||
return kbxFieldCatalog[key]
|
||||
}
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
// generated from contracts/integrations/kbx.integrations.json; do not edit.
|
||||
import type { KbxIntegrationDefinition } from '../integration'
|
||||
export const kbxIntegrationSourceSha256 = '607853e43ab35fdacc1adea7d5b470dfad791f6718afba215b5600c974b0642e' as const
|
||||
export const kbxIntegrationCatalog = {
|
||||
"integration.oms.wms.dispatch": {
|
||||
"id": "integration.oms.wms.dispatch",
|
||||
"title": "OMS → WMS 출고지시 전달",
|
||||
"ownerModule": "OMS",
|
||||
"direction": "outbound",
|
||||
"transport": "outbox-http",
|
||||
"criticality": "high",
|
||||
"sourceEvent": "OrderShipmentRequested",
|
||||
"target": "WMS",
|
||||
"delivery": "at-least-once",
|
||||
"ordering": "per-aggregate",
|
||||
"idempotency": "event-id",
|
||||
"timeoutMs": 3000,
|
||||
"shortRetry": {
|
||||
"maxRetryAttempts": 2,
|
||||
"baseDelayMs": 250,
|
||||
"backoff": "exponential"
|
||||
},
|
||||
"longRetry": {
|
||||
"scheduler": "hangfire",
|
||||
"maxAttempts": 8,
|
||||
"scheduleSeconds": [
|
||||
10,
|
||||
30,
|
||||
120,
|
||||
300,
|
||||
900,
|
||||
1800,
|
||||
3600,
|
||||
7200
|
||||
]
|
||||
},
|
||||
"circuitBreaker": {
|
||||
"failureRatio": 0.5,
|
||||
"samplingSeconds": 30,
|
||||
"minimumThroughput": 10,
|
||||
"breakSeconds": 30
|
||||
},
|
||||
"retryable": [
|
||||
"network",
|
||||
"timeout",
|
||||
"http-408",
|
||||
"http-429",
|
||||
"http-5xx",
|
||||
"circuit-open"
|
||||
],
|
||||
"permanent": [
|
||||
"contract-invalid",
|
||||
"http-400",
|
||||
"http-401",
|
||||
"http-403",
|
||||
"http-404",
|
||||
"domain-rejected"
|
||||
],
|
||||
"terminalAction": "operations-exception",
|
||||
"userVisible": true
|
||||
},
|
||||
"integration.wms.oms.picking-result": {
|
||||
"id": "integration.wms.oms.picking-result",
|
||||
"title": "WMS → OMS 피킹결과 전달",
|
||||
"ownerModule": "WMS",
|
||||
"direction": "outbound",
|
||||
"transport": "outbox-http",
|
||||
"criticality": "high",
|
||||
"sourceEvent": "PickingCompleted",
|
||||
"target": "OMS",
|
||||
"delivery": "at-least-once",
|
||||
"ordering": "per-aggregate",
|
||||
"idempotency": "event-id",
|
||||
"timeoutMs": 3000,
|
||||
"shortRetry": {
|
||||
"maxRetryAttempts": 2,
|
||||
"baseDelayMs": 250,
|
||||
"backoff": "exponential"
|
||||
},
|
||||
"longRetry": {
|
||||
"scheduler": "hangfire",
|
||||
"maxAttempts": 8,
|
||||
"scheduleSeconds": [
|
||||
10,
|
||||
30,
|
||||
120,
|
||||
300,
|
||||
900,
|
||||
1800,
|
||||
3600,
|
||||
7200
|
||||
]
|
||||
},
|
||||
"circuitBreaker": {
|
||||
"failureRatio": 0.5,
|
||||
"samplingSeconds": 30,
|
||||
"minimumThroughput": 10,
|
||||
"breakSeconds": 30
|
||||
},
|
||||
"retryable": [
|
||||
"network",
|
||||
"timeout",
|
||||
"http-408",
|
||||
"http-429",
|
||||
"http-5xx",
|
||||
"circuit-open"
|
||||
],
|
||||
"permanent": [
|
||||
"contract-invalid",
|
||||
"http-400",
|
||||
"http-401",
|
||||
"http-403",
|
||||
"http-404",
|
||||
"domain-rejected"
|
||||
],
|
||||
"terminalAction": "operations-exception",
|
||||
"userVisible": true
|
||||
},
|
||||
"integration.carrier.tracking": {
|
||||
"id": "integration.carrier.tracking",
|
||||
"title": "배송사 송장/배송상태 연계",
|
||||
"ownerModule": "OMS",
|
||||
"direction": "outbound",
|
||||
"transport": "outbox-http",
|
||||
"criticality": "medium",
|
||||
"sourceEvent": "TrackingSubmissionRequested",
|
||||
"target": "CarrierGateway",
|
||||
"delivery": "at-least-once",
|
||||
"ordering": "none",
|
||||
"idempotency": "business-key",
|
||||
"timeoutMs": 5000,
|
||||
"shortRetry": {
|
||||
"maxRetryAttempts": 2,
|
||||
"baseDelayMs": 500,
|
||||
"backoff": "exponential"
|
||||
},
|
||||
"longRetry": {
|
||||
"scheduler": "hangfire",
|
||||
"maxAttempts": 6,
|
||||
"scheduleSeconds": [
|
||||
30,
|
||||
120,
|
||||
600,
|
||||
1800,
|
||||
3600,
|
||||
7200
|
||||
]
|
||||
},
|
||||
"circuitBreaker": {
|
||||
"failureRatio": 0.5,
|
||||
"samplingSeconds": 60,
|
||||
"minimumThroughput": 10,
|
||||
"breakSeconds": 60
|
||||
},
|
||||
"retryable": [
|
||||
"network",
|
||||
"timeout",
|
||||
"http-408",
|
||||
"http-429",
|
||||
"http-5xx",
|
||||
"circuit-open"
|
||||
],
|
||||
"permanent": [
|
||||
"contract-invalid",
|
||||
"http-400",
|
||||
"http-401",
|
||||
"http-403",
|
||||
"http-404",
|
||||
"domain-rejected"
|
||||
],
|
||||
"terminalAction": "operations-exception",
|
||||
"userVisible": true
|
||||
}
|
||||
} as const satisfies Record<string,KbxIntegrationDefinition>
|
||||
export type KbxIntegrationId = keyof typeof kbxIntegrationCatalog
|
||||
+574
@@ -0,0 +1,574 @@
|
||||
// generated from contracts/authorization/kbx.authorization.json
|
||||
export const kbxPermissionCatalog = [
|
||||
{
|
||||
"id": "common.ai.use",
|
||||
"module": "COMMON",
|
||||
"resource": "ai",
|
||||
"action": "use",
|
||||
"risk": "medium",
|
||||
"description": "AI 설명·추천·초안 기능 사용",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.ai.execute",
|
||||
"module": "COMMON",
|
||||
"resource": "ai",
|
||||
"action": "execute",
|
||||
"risk": "high",
|
||||
"description": "AI 승인 제안의 실제 Command 실행 허용",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.operations.claim",
|
||||
"module": "COMMON",
|
||||
"resource": "operations",
|
||||
"action": "claim",
|
||||
"risk": "medium",
|
||||
"description": "업무 예외를 내 처리건으로 지정",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.operations.create",
|
||||
"module": "COMMON",
|
||||
"resource": "operations",
|
||||
"action": "create",
|
||||
"risk": "medium",
|
||||
"description": "대사 결과에서 운영 예외 생성",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.operations.read",
|
||||
"module": "COMMON",
|
||||
"resource": "operations",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "업무 예외 센터 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.operations.resolve",
|
||||
"module": "COMMON",
|
||||
"resource": "operations",
|
||||
"action": "resolve",
|
||||
"risk": "high",
|
||||
"description": "수동 해결이 허용된 운영 예외 해결",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.operations.retry",
|
||||
"module": "COMMON",
|
||||
"resource": "operations",
|
||||
"action": "retry",
|
||||
"risk": "high",
|
||||
"description": "등록된 안전한 예외 Action 재처리",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.reconcile.read",
|
||||
"module": "COMMON",
|
||||
"resource": "reconcile",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "업무 데이터 대사 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.runtime.read",
|
||||
"module": "COMMON",
|
||||
"resource": "runtime",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "런타임 상태·작업·알림 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.suggestion.create",
|
||||
"module": "COMMON",
|
||||
"resource": "suggestion",
|
||||
"action": "create",
|
||||
"risk": "low",
|
||||
"description": "현재 화면 사용자 제안 등록",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.inventory.move.confirm",
|
||||
"module": "ERP",
|
||||
"resource": "inventory-move",
|
||||
"action": "confirm",
|
||||
"risk": "high",
|
||||
"description": "재고이동 확정",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.inventory.move.read",
|
||||
"module": "ERP",
|
||||
"resource": "inventory-move",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "재고이동 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.inventory.move.receive",
|
||||
"module": "ERP",
|
||||
"resource": "inventory-move",
|
||||
"action": "receive",
|
||||
"risk": "high",
|
||||
"description": "이동재고 입고완료",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.inventory.move.ship",
|
||||
"module": "ERP",
|
||||
"resource": "inventory-move",
|
||||
"action": "ship",
|
||||
"risk": "high",
|
||||
"description": "이동재고 출고",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.inventory.move.write",
|
||||
"module": "ERP",
|
||||
"resource": "inventory-move",
|
||||
"action": "write",
|
||||
"risk": "medium",
|
||||
"description": "재고이동 작성·수정",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.inventory.read",
|
||||
"module": "ERP",
|
||||
"resource": "inventory",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "재고현황 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.item.price.read",
|
||||
"module": "ERP",
|
||||
"resource": "item-price",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "품목 단가 일괄등록 화면 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.item.price.write",
|
||||
"module": "ERP",
|
||||
"resource": "item-price",
|
||||
"action": "write",
|
||||
"risk": "medium",
|
||||
"description": "품목 단가 일괄등록·수정",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.item.create",
|
||||
"module": "ERP",
|
||||
"resource": "item",
|
||||
"action": "create",
|
||||
"risk": "medium",
|
||||
"description": "품목 신규·복사",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.item.read",
|
||||
"module": "ERP",
|
||||
"resource": "item",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "품목 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.item.write",
|
||||
"module": "ERP",
|
||||
"resource": "item",
|
||||
"action": "write",
|
||||
"risk": "medium",
|
||||
"description": "품목 수정·사용중지",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.purchase.cancel",
|
||||
"module": "ERP",
|
||||
"resource": "purchase",
|
||||
"action": "cancel",
|
||||
"risk": "high",
|
||||
"description": "구매 취소",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.purchase.confirm",
|
||||
"module": "ERP",
|
||||
"resource": "purchase",
|
||||
"action": "confirm",
|
||||
"risk": "high",
|
||||
"description": "구매 확정",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.purchase.read",
|
||||
"module": "ERP",
|
||||
"resource": "purchase",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "구매 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "erp.purchase.write",
|
||||
"module": "ERP",
|
||||
"resource": "purchase",
|
||||
"action": "write",
|
||||
"risk": "medium",
|
||||
"description": "구매 작성·수정",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "imports.execute",
|
||||
"module": "COMMON",
|
||||
"resource": "imports",
|
||||
"action": "execute",
|
||||
"risk": "high",
|
||||
"description": "Excel Import 생성·검증·반영",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "kbx.design.read",
|
||||
"module": "COMMON",
|
||||
"resource": "design-system",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "KBX 내부 컴포넌트 카탈로그 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.claim.approve",
|
||||
"module": "OMS",
|
||||
"resource": "claim",
|
||||
"action": "approve",
|
||||
"risk": "high",
|
||||
"description": "클레임 승인",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.claim.hold",
|
||||
"module": "OMS",
|
||||
"resource": "claim",
|
||||
"action": "hold",
|
||||
"risk": "medium",
|
||||
"description": "클레임 보류",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.claim.process",
|
||||
"module": "OMS",
|
||||
"resource": "claim",
|
||||
"action": "process",
|
||||
"risk": "high",
|
||||
"description": "클레임 처리 시작·완료",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.claim.read",
|
||||
"module": "OMS",
|
||||
"resource": "claim",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "반품·클레임 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.order.create",
|
||||
"module": "OMS",
|
||||
"resource": "order",
|
||||
"action": "create",
|
||||
"risk": "medium",
|
||||
"description": "주문 신규 등록",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.order.import",
|
||||
"module": "OMS",
|
||||
"resource": "order",
|
||||
"action": "import",
|
||||
"risk": "high",
|
||||
"description": "주문 Excel Import 실행",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.order.read",
|
||||
"module": "OMS",
|
||||
"resource": "order",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "주문 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.order.ship",
|
||||
"module": "OMS",
|
||||
"resource": "order",
|
||||
"action": "ship",
|
||||
"risk": "high",
|
||||
"description": "주문 출고지시",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.order.recipient.unmask",
|
||||
"module": "OMS",
|
||||
"resource": "order-recipient",
|
||||
"action": "sensitive-read",
|
||||
"risk": "high",
|
||||
"description": "주문 수취인 개인정보 전체보기",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.order.recipient.export",
|
||||
"module": "OMS",
|
||||
"resource": "order-recipient",
|
||||
"action": "sensitive-export",
|
||||
"risk": "high",
|
||||
"description": "주문 수취인 개인정보 비마스킹 Export",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "wms.inventory.count",
|
||||
"module": "WMS",
|
||||
"resource": "inventory",
|
||||
"action": "count",
|
||||
"risk": "high",
|
||||
"description": "현장 재고실사 실행",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "wms.picking.execute",
|
||||
"module": "WMS",
|
||||
"resource": "picking",
|
||||
"action": "execute",
|
||||
"risk": "high",
|
||||
"description": "출고 피킹 작업 실행",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "wms.putaway.execute",
|
||||
"module": "WMS",
|
||||
"resource": "putaway",
|
||||
"action": "execute",
|
||||
"risk": "high",
|
||||
"description": "입고 적치 작업 실행",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "wms.receiving.execute",
|
||||
"module": "WMS",
|
||||
"resource": "receiving",
|
||||
"action": "execute",
|
||||
"risk": "high",
|
||||
"description": "입고 검수 작업 실행",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "wms.work.execute",
|
||||
"module": "WMS",
|
||||
"resource": "work",
|
||||
"action": "execute",
|
||||
"risk": "high",
|
||||
"description": "WMS 작업 시작",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "wms.work.read",
|
||||
"module": "WMS",
|
||||
"resource": "work",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "WMS 작업 Queue 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.telemetry.write",
|
||||
"module": "COMMON",
|
||||
"resource": "telemetry",
|
||||
"action": "write",
|
||||
"risk": "low",
|
||||
"description": "민감정보를 포함하지 않는 KBX 의미 단위 UX Telemetry 전송",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.ux.read",
|
||||
"module": "COMMON",
|
||||
"resource": "ux-metrics",
|
||||
"action": "read",
|
||||
"risk": "medium",
|
||||
"description": "KBX UX 품질·자동화 지표 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.experiment.evaluate",
|
||||
"module": "COMMON",
|
||||
"resource": "experiment",
|
||||
"action": "evaluate",
|
||||
"risk": "low",
|
||||
"description": "현재 사용자에 대한 안전한 UX 실험 Variant 평가",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.experiment.read",
|
||||
"module": "COMMON",
|
||||
"resource": "experiment",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "KBX UX 실험·점진배포 상태 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.experiment.manage",
|
||||
"module": "COMMON",
|
||||
"resource": "experiment",
|
||||
"action": "manage",
|
||||
"risk": "high",
|
||||
"description": "UX 실험 점진배포 비율 변경·일시중지·즉시 롤백",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.integration.read",
|
||||
"module": "COMMON",
|
||||
"resource": "integration",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "업무 외부연계 상태·시도 이력 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.integration.retry",
|
||||
"module": "COMMON",
|
||||
"resource": "integration",
|
||||
"action": "retry",
|
||||
"risk": "high",
|
||||
"description": "최종 실패한 idempotent 외부연계의 수동 재처리 예약",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.external-data.read",
|
||||
"module": "COMMON",
|
||||
"resource": "external-data",
|
||||
"action": "read",
|
||||
"risk": "low",
|
||||
"description": "외부 데이터셋의 출처·신선도·캐시 상태 조회",
|
||||
"presentation": "hide",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "common.external-data.refresh",
|
||||
"module": "COMMON",
|
||||
"resource": "external-data",
|
||||
"action": "refresh",
|
||||
"risk": "medium",
|
||||
"description": "승인된 외부 데이터셋의 명시적 재수집 요청",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.order.confirm",
|
||||
"module": "OMS",
|
||||
"resource": "order",
|
||||
"action": "confirm",
|
||||
"risk": "high",
|
||||
"description": "작성 주문 확정",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
},
|
||||
{
|
||||
"id": "oms.order.write",
|
||||
"module": "OMS",
|
||||
"resource": "order",
|
||||
"action": "write",
|
||||
"risk": "medium",
|
||||
"description": "작성 상태 주문 수정",
|
||||
"presentation": "disable",
|
||||
"backendRequired": true
|
||||
}
|
||||
] as const
|
||||
export const kbxSensitiveDataPolicies = [
|
||||
{
|
||||
"id": "oms.order.recipient",
|
||||
"fields": [
|
||||
"receiverName",
|
||||
"phone",
|
||||
"postalCode",
|
||||
"address1",
|
||||
"address2"
|
||||
],
|
||||
"defaultExposure": "masked",
|
||||
"viewPermission": "oms.order.read",
|
||||
"revealPermission": "oms.order.recipient.unmask",
|
||||
"unmaskedExportPermission": "oms.order.recipient.export",
|
||||
"auditRequired": true,
|
||||
"aiExposure": "masked-only",
|
||||
"telemetryExposure": "never",
|
||||
"reasonRequired": false
|
||||
}
|
||||
] as const
|
||||
export const kbxAiAuthorizationPolicy = {
|
||||
"usePermission": "common.ai.use",
|
||||
"executePermission": "common.ai.execute",
|
||||
"executeRequiresProposalPermission": true,
|
||||
"defaultCapabilities": [
|
||||
"explain",
|
||||
"suggest",
|
||||
"draft"
|
||||
]
|
||||
} as const
|
||||
export type KbxPermissionId = typeof kbxPermissionCatalog[number]['id']
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
// generated from contracts/providers/kbx.providers.json; do not edit.
|
||||
import type { KbxExternalProviderDefinition } from '../provider'
|
||||
export const kbxProviderSourceSha256='5515e5e002767ed895ea0442003829b0bad8fa9c7a0693ce6cdcbd65969b830f' as const
|
||||
export const kbxExternalProviderCatalog={
|
||||
"provider.krx.openapi": {
|
||||
"id": "provider.krx.openapi",
|
||||
"title": "KRX Data Marketplace OPEN API",
|
||||
"ownerModule": "COMMON",
|
||||
"purpose": "market-data-readonly",
|
||||
"mutationAllowed": false,
|
||||
"officialSources": [
|
||||
"https://openapi.krx.co.kr/contents/OPP/INFO/OPPINFO003.jsp",
|
||||
"https://openapi.krx.co.kr/contents/OPP/INFO/service/OPPINFO004.cmd"
|
||||
],
|
||||
"official": {
|
||||
"approvalRequired": true,
|
||||
"authentication": {
|
||||
"type": "header-api-key",
|
||||
"headerName": "AUTH_KEY"
|
||||
},
|
||||
"serviceUrlPolicy": "service-specific-from-approved-KRX-definition",
|
||||
"dataAvailabilityNote": "서비스 목록은 다수 데이터에 대해 2010년 이후 제공범위를 안내함",
|
||||
"numericRateLimit": null
|
||||
},
|
||||
"kbxPolicy": {
|
||||
"allowedHostSuffix": ".krx.co.kr",
|
||||
"credentialKey": "ExternalProviders:Krx:AuthKey",
|
||||
"maxConcurrency": 2,
|
||||
"timeoutMs": 5000,
|
||||
"retryHttpStatuses": [
|
||||
408,
|
||||
429,
|
||||
500,
|
||||
502,
|
||||
503,
|
||||
504
|
||||
],
|
||||
"maxRetryAttempts": 1,
|
||||
"serviceDefinitionRequired": true,
|
||||
"cacheable": true
|
||||
},
|
||||
"operations": [
|
||||
{
|
||||
"id": "krx.approved-service.invoke",
|
||||
"method": "provider-defined-read",
|
||||
"path": "provider-defined",
|
||||
"response": "json-or-xml",
|
||||
"notes": "실제 URL/메서드는 KRX에서 승인된 개별 서비스 명세를 구성값으로 등록. 저장소에서 추정하지 않음."
|
||||
}
|
||||
]
|
||||
},
|
||||
"provider.opendart": {
|
||||
"id": "provider.opendart",
|
||||
"title": "금융감독원 OPENDART OpenAPI",
|
||||
"ownerModule": "COMMON",
|
||||
"purpose": "disclosure-data-readonly",
|
||||
"mutationAllowed": false,
|
||||
"officialSources": [
|
||||
"https://opendart.fss.or.kr/guide/detail.do?apiGrpCd=DS001&apiId=2019001",
|
||||
"https://opendart.fss.or.kr/guide/detail.do?apiGrpCd=DS001&apiId=2019002",
|
||||
"https://opendart.fss.or.kr/guide/detail.do?apiGrpCd=DS001&apiId=2019018"
|
||||
],
|
||||
"official": {
|
||||
"baseUri": "https://opendart.fss.or.kr/api/",
|
||||
"authentication": {
|
||||
"type": "query-api-key",
|
||||
"parameterName": "crtfc_key",
|
||||
"length": 40
|
||||
},
|
||||
"statusField": "status",
|
||||
"messageField": "message",
|
||||
"statusCodes": {
|
||||
"100": "invalid-field",
|
||||
"101": "invalid-access",
|
||||
"800": "maintenance",
|
||||
"900": "undefined-error",
|
||||
"901": "expired-personal-data-retention",
|
||||
"000": "success",
|
||||
"010": "unregistered-key",
|
||||
"011": "disabled-key",
|
||||
"012": "forbidden-ip",
|
||||
"013": "no-data",
|
||||
"014": "file-missing",
|
||||
"020": "request-limit-exceeded",
|
||||
"021": "company-count-exceeded"
|
||||
},
|
||||
"rateLimitNote": "020은 일반적으로 20,000건 이상의 요청에서 발생할 수 있으나 서비스별 제한이 다를 수 있음"
|
||||
},
|
||||
"kbxPolicy": {
|
||||
"credentialKey": "ExternalProviders:OpenDart:ApiKey",
|
||||
"timeoutMs": 5000,
|
||||
"maxConcurrency": 2,
|
||||
"retryStatusCodes": [
|
||||
"020",
|
||||
"800",
|
||||
"900"
|
||||
],
|
||||
"maxRetryAttempts": 1,
|
||||
"noDataStatusCodes": [
|
||||
"013"
|
||||
],
|
||||
"cacheable": true
|
||||
},
|
||||
"operations": [
|
||||
{
|
||||
"id": "opendart.disclosures",
|
||||
"method": "GET",
|
||||
"path": "list.json",
|
||||
"response": "json"
|
||||
},
|
||||
{
|
||||
"id": "opendart.company",
|
||||
"method": "GET",
|
||||
"path": "company.json",
|
||||
"response": "json"
|
||||
},
|
||||
{
|
||||
"id": "opendart.corp-code",
|
||||
"method": "GET",
|
||||
"path": "corpCode.xml",
|
||||
"response": "zip-binary"
|
||||
}
|
||||
]
|
||||
},
|
||||
"provider.kis.market-data": {
|
||||
"id": "provider.kis.market-data",
|
||||
"title": "한국투자증권 KIS Open API — 국내주식 시세",
|
||||
"ownerModule": "COMMON",
|
||||
"purpose": "market-data-readonly",
|
||||
"mutationAllowed": false,
|
||||
"officialSources": [
|
||||
"https://apiportal.koreainvestment.com/apiservice-apiservice",
|
||||
"https://apiportal.koreainvestment.com/community/10000000-0000-0011-0000-000000000001/post/d0d1a83f-6f8d-4437-9700-6d26702fd989",
|
||||
"https://github.com/koreainvestment/open-trading-api/blob/main/examples_llm/domestic_stock/inquire_price/inquire_price.py",
|
||||
"https://github.com/koreainvestment/open-trading-api/blob/main/examples_llm/kis_auth.py"
|
||||
],
|
||||
"official": {
|
||||
"productionBaseUri": "https://openapi.koreainvestment.com:9443",
|
||||
"sandboxBaseUri": "https://openapivts.koreainvestment.com:29443",
|
||||
"authentication": {
|
||||
"type": "oauth2-client-credentials",
|
||||
"tokenPath": "/oauth2/tokenP",
|
||||
"bodyFields": [
|
||||
"grant_type",
|
||||
"appkey",
|
||||
"appsecret"
|
||||
],
|
||||
"grantType": "client_credentials"
|
||||
},
|
||||
"tokenValidityHours": 24,
|
||||
"tokenRenewalCycleHours": 6,
|
||||
"headers": [
|
||||
"authorization",
|
||||
"appkey",
|
||||
"appsecret",
|
||||
"tr_id",
|
||||
"custtype",
|
||||
"tr_cont"
|
||||
],
|
||||
"responseSuccess": {
|
||||
"field": "rt_cd",
|
||||
"value": "0"
|
||||
},
|
||||
"rateLimitsAsOf": "2026-04-20",
|
||||
"productionRequestsPerSecond": 18,
|
||||
"sandboxRequestsPerSecond": 1,
|
||||
"tokenRequestsPerSecond": 1,
|
||||
"concurrentSpacingRecommendationMs": [
|
||||
100,
|
||||
150
|
||||
]
|
||||
},
|
||||
"kbxPolicy": {
|
||||
"appKeyCredential": "ExternalProviders:Kis:AppKey",
|
||||
"appSecretCredential": "ExternalProviders:Kis:AppSecret",
|
||||
"environmentKey": "ExternalProviders:Kis:Environment",
|
||||
"readOnlyOnly": true,
|
||||
"tokenRefreshSkewMinutes": 5,
|
||||
"productionMinimumSpacingMs": 100,
|
||||
"sandboxMinimumSpacingMs": 1000,
|
||||
"timeoutMs": 5000,
|
||||
"maxRetryAttempts": 1,
|
||||
"retryHttpStatuses": [
|
||||
408,
|
||||
429,
|
||||
500,
|
||||
502,
|
||||
503,
|
||||
504
|
||||
],
|
||||
"cacheable": true
|
||||
},
|
||||
"operations": [
|
||||
{
|
||||
"id": "kis.oauth.token",
|
||||
"method": "POST",
|
||||
"path": "/oauth2/tokenP",
|
||||
"response": "json",
|
||||
"authOperation": true
|
||||
},
|
||||
{
|
||||
"id": "kis.domestic-stock.current-price",
|
||||
"method": "GET",
|
||||
"path": "/uapi/domestic-stock/v1/quotations/inquire-price",
|
||||
"trId": "FHKST01010100",
|
||||
"response": "json",
|
||||
"query": [
|
||||
"FID_COND_MRKT_DIV_CODE",
|
||||
"FID_INPUT_ISCD"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
} as const satisfies Record<string,KbxExternalProviderDefinition>
|
||||
export type KbxExternalProviderId=keyof typeof kbxExternalProviderCatalog
|
||||
+956
@@ -0,0 +1,956 @@
|
||||
// generated from contracts/screens/kbx.screen-recipes.json; do not edit.
|
||||
// SHA256: 97ab56bc54149f32ea16577369c4ec29579b516ea464cb42010b31e4dc413e60
|
||||
import type { KbxScreenRecipeDefinition } from '../screen'
|
||||
|
||||
export const kbxScreenRecipeContractVersion="1.1.0" as const
|
||||
export const kbxScreenRecipeCatalog={
|
||||
"T01": {
|
||||
"code": "T01",
|
||||
"type": "list",
|
||||
"templateComponent": "KbxListPage",
|
||||
"defaultCommands": [
|
||||
{
|
||||
"id": "search",
|
||||
"label": "조회",
|
||||
"group": "query",
|
||||
"shortcut": "F3",
|
||||
"permissionKind": "none"
|
||||
},
|
||||
{
|
||||
"id": "excel",
|
||||
"label": "엑셀",
|
||||
"group": "output",
|
||||
"permissionKind": "none"
|
||||
}
|
||||
],
|
||||
"requiredPolicies": [
|
||||
"server-read-model",
|
||||
"tanstack-query",
|
||||
"search-condition-preservation",
|
||||
"server-side-bulk-selection"
|
||||
],
|
||||
"recoveryPolicies": [
|
||||
"idle-before-first-search",
|
||||
"retain-grid-during-refresh",
|
||||
"retry-with-search-context",
|
||||
"partial-bulk-result"
|
||||
],
|
||||
"securityPolicies": [
|
||||
"screen-permission",
|
||||
"command-permission",
|
||||
"safe-drilldown-route",
|
||||
"masked-sensitive-cells"
|
||||
],
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.oms.order-list.bulk-ship",
|
||||
"scenario.oms.order-list.all-filtered-ship"
|
||||
],
|
||||
"scaffoldSurfaces": [
|
||||
"search",
|
||||
"content",
|
||||
"summary"
|
||||
],
|
||||
"testProfile": {
|
||||
"requiredScenarioKinds": [
|
||||
"e2e"
|
||||
],
|
||||
"requiredTags": [
|
||||
"bulk",
|
||||
"idempotency"
|
||||
],
|
||||
"requiredEvidence": [
|
||||
"playwright-trace"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"idle-search",
|
||||
"refresh-retains-context",
|
||||
"bulk-partial-result",
|
||||
"safe-drilldown"
|
||||
]
|
||||
}
|
||||
},
|
||||
"T02": {
|
||||
"code": "T02",
|
||||
"type": "master",
|
||||
"templateComponent": "KbxMasterPage",
|
||||
"defaultCommands": [
|
||||
{
|
||||
"id": "search",
|
||||
"label": "조회",
|
||||
"group": "query",
|
||||
"shortcut": "F3",
|
||||
"permissionKind": "none"
|
||||
},
|
||||
{
|
||||
"id": "new",
|
||||
"label": "신규",
|
||||
"group": "edit",
|
||||
"permissionKind": "write"
|
||||
},
|
||||
{
|
||||
"id": "save",
|
||||
"label": "저장",
|
||||
"group": "edit",
|
||||
"shortcut": "F8",
|
||||
"variant": "primary",
|
||||
"permissionKind": "write"
|
||||
},
|
||||
{
|
||||
"id": "excel",
|
||||
"label": "엑셀",
|
||||
"group": "output",
|
||||
"permissionKind": "none"
|
||||
}
|
||||
],
|
||||
"requiredPolicies": [
|
||||
"normalized-write-model",
|
||||
"lookup-provider",
|
||||
"server-validation",
|
||||
"optimistic-concurrency",
|
||||
"audit"
|
||||
],
|
||||
"recoveryPolicies": [
|
||||
"dirty-navigation-guard",
|
||||
"conflict-reload",
|
||||
"field-validation-focus",
|
||||
"readonly-after-terminal-state"
|
||||
],
|
||||
"securityPolicies": [
|
||||
"screen-permission",
|
||||
"write-command-permission",
|
||||
"server-enforcement",
|
||||
"sensitive-value-masking"
|
||||
],
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.erp.item-master.lifecycle",
|
||||
"scenario.erp.item-master.keyboard-recovery"
|
||||
],
|
||||
"scaffoldSurfaces": [
|
||||
"list",
|
||||
"detail"
|
||||
],
|
||||
"testProfile": {
|
||||
"requiredScenarioKinds": [
|
||||
"e2e",
|
||||
"integration"
|
||||
],
|
||||
"requiredTags": [
|
||||
"master-crud",
|
||||
"concurrency",
|
||||
"audit"
|
||||
],
|
||||
"requiredEvidence": [
|
||||
"playwright-trace",
|
||||
"db-assertions"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"permission-aware-save",
|
||||
"dirty-guard",
|
||||
"conflict-reload",
|
||||
"audit-visible"
|
||||
]
|
||||
}
|
||||
},
|
||||
"T03": {
|
||||
"code": "T03",
|
||||
"type": "transaction",
|
||||
"templateComponent": "KbxTransactionPage",
|
||||
"defaultCommands": [
|
||||
{
|
||||
"id": "new",
|
||||
"label": "신규",
|
||||
"group": "edit",
|
||||
"permissionKind": "write"
|
||||
},
|
||||
{
|
||||
"id": "save",
|
||||
"label": "저장",
|
||||
"group": "edit",
|
||||
"shortcut": "F8",
|
||||
"variant": "primary",
|
||||
"permissionKind": "write"
|
||||
},
|
||||
{
|
||||
"id": "excel",
|
||||
"label": "엑셀",
|
||||
"group": "output",
|
||||
"permissionKind": "none"
|
||||
}
|
||||
],
|
||||
"requiredPolicies": [
|
||||
"normalized-write-model",
|
||||
"header-detail-transaction",
|
||||
"server-validation",
|
||||
"optimistic-concurrency",
|
||||
"audit",
|
||||
"outbox"
|
||||
],
|
||||
"recoveryPolicies": [
|
||||
"dirty-navigation-guard",
|
||||
"conflict-reload",
|
||||
"row-key-validation",
|
||||
"double-submit-guard"
|
||||
],
|
||||
"securityPolicies": [
|
||||
"screen-permission",
|
||||
"write-command-permission",
|
||||
"workflow-permission",
|
||||
"server-enforcement"
|
||||
],
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.oms.order-register.keyboard",
|
||||
"scenario.oms.order-register.conflict",
|
||||
"scenario.oms.order-register.lifecycle"
|
||||
],
|
||||
"scaffoldSurfaces": [
|
||||
"header",
|
||||
"detail",
|
||||
"summary"
|
||||
],
|
||||
"testProfile": {
|
||||
"requiredScenarioKinds": [
|
||||
"e2e",
|
||||
"integration"
|
||||
],
|
||||
"requiredTags": [
|
||||
"keyboard",
|
||||
"lookup",
|
||||
"conflict",
|
||||
"workflow"
|
||||
],
|
||||
"requiredEvidence": [
|
||||
"playwright-trace",
|
||||
"problem-json"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"f2-lookup",
|
||||
"f8-save",
|
||||
"row-key-validation",
|
||||
"conflict-recovery"
|
||||
]
|
||||
}
|
||||
},
|
||||
"T04": {
|
||||
"code": "T04",
|
||||
"type": "fast-entry",
|
||||
"templateComponent": "KbxFastEntryPage",
|
||||
"defaultCommands": [
|
||||
{
|
||||
"id": "new",
|
||||
"label": "신규",
|
||||
"group": "edit",
|
||||
"permissionKind": "write"
|
||||
},
|
||||
{
|
||||
"id": "save",
|
||||
"label": "저장",
|
||||
"group": "edit",
|
||||
"shortcut": "F8",
|
||||
"variant": "primary",
|
||||
"permissionKind": "write"
|
||||
},
|
||||
{
|
||||
"id": "excel",
|
||||
"label": "엑셀",
|
||||
"group": "output",
|
||||
"permissionKind": "none"
|
||||
}
|
||||
],
|
||||
"requiredPolicies": [
|
||||
"typed-clipboard-normalization",
|
||||
"stable-client-row-key",
|
||||
"bulk-server-validation",
|
||||
"idempotent-bulk-save"
|
||||
],
|
||||
"recoveryPolicies": [
|
||||
"error-cell-navigation",
|
||||
"paste-error-summary",
|
||||
"dirty-navigation-guard",
|
||||
"partial-save-result"
|
||||
],
|
||||
"securityPolicies": [
|
||||
"screen-permission",
|
||||
"write-command-permission",
|
||||
"lookup-entity-resolution",
|
||||
"server-enforcement"
|
||||
],
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.erp.item-price.fast-entry",
|
||||
"scenario.oms.order-register.fast-entry"
|
||||
],
|
||||
"scaffoldSurfaces": [
|
||||
"guide",
|
||||
"content",
|
||||
"validation",
|
||||
"summary"
|
||||
],
|
||||
"testProfile": {
|
||||
"requiredScenarioKinds": [
|
||||
"e2e"
|
||||
],
|
||||
"requiredTags": [
|
||||
"fast-entry",
|
||||
"paste",
|
||||
"fill-down",
|
||||
"idempotency"
|
||||
],
|
||||
"requiredEvidence": [
|
||||
"playwright-trace",
|
||||
"problem-json"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"multi-cell-paste",
|
||||
"fill-down",
|
||||
"error-navigation",
|
||||
"partial-save-result"
|
||||
]
|
||||
}
|
||||
},
|
||||
"T05": {
|
||||
"code": "T05",
|
||||
"type": "master-detail",
|
||||
"templateComponent": "KbxMasterDetailPage",
|
||||
"defaultCommands": [
|
||||
{
|
||||
"id": "search",
|
||||
"label": "조회",
|
||||
"group": "query",
|
||||
"shortcut": "F3",
|
||||
"permissionKind": "none"
|
||||
},
|
||||
{
|
||||
"id": "excel",
|
||||
"label": "엑셀",
|
||||
"group": "output",
|
||||
"permissionKind": "none"
|
||||
}
|
||||
],
|
||||
"requiredPolicies": [
|
||||
"server-read-model",
|
||||
"master-selection-context",
|
||||
"detail-projection",
|
||||
"n-plus-one-prohibition"
|
||||
],
|
||||
"recoveryPolicies": [
|
||||
"selection-restore-after-refresh",
|
||||
"retain-master-on-detail-error",
|
||||
"safe-drilldown",
|
||||
"empty-master-detail-reset"
|
||||
],
|
||||
"securityPolicies": [
|
||||
"screen-permission",
|
||||
"safe-drilldown-route",
|
||||
"masked-sensitive-detail"
|
||||
],
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.erp.inventory.master-detail-context"
|
||||
],
|
||||
"scaffoldSurfaces": [
|
||||
"search",
|
||||
"master",
|
||||
"detail"
|
||||
],
|
||||
"testProfile": {
|
||||
"requiredScenarioKinds": [
|
||||
"e2e"
|
||||
],
|
||||
"requiredTags": [
|
||||
"master-detail",
|
||||
"context-retention",
|
||||
"drill-down"
|
||||
],
|
||||
"requiredEvidence": [
|
||||
"playwright-trace",
|
||||
"api-transcript"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"master-selection-context",
|
||||
"detail-error-retains-master",
|
||||
"history-context",
|
||||
"safe-drilldown"
|
||||
]
|
||||
}
|
||||
},
|
||||
"T06": {
|
||||
"code": "T06",
|
||||
"type": "queue",
|
||||
"templateComponent": "KbxQueuePage",
|
||||
"defaultCommands": [
|
||||
{
|
||||
"id": "search",
|
||||
"label": "조회",
|
||||
"group": "query",
|
||||
"shortcut": "F3",
|
||||
"permissionKind": "none"
|
||||
}
|
||||
],
|
||||
"requiredPolicies": [
|
||||
"exception-first-projection",
|
||||
"sla-state",
|
||||
"server-side-bulk-selection",
|
||||
"audit"
|
||||
],
|
||||
"recoveryPolicies": [
|
||||
"partial-action-result",
|
||||
"retryable-vs-terminal-error",
|
||||
"stale-event-suppression",
|
||||
"detail-context-retention"
|
||||
],
|
||||
"securityPolicies": [
|
||||
"screen-permission",
|
||||
"exception-action-permission",
|
||||
"server-enforcement"
|
||||
],
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.common.operations.stale-event",
|
||||
"scenario.integration.manual-retry.idempotent",
|
||||
"scenario.common.operations.queue-recovery"
|
||||
],
|
||||
"scaffoldSurfaces": [
|
||||
"summary",
|
||||
"exceptions",
|
||||
"content"
|
||||
],
|
||||
"testProfile": {
|
||||
"requiredScenarioKinds": [
|
||||
"e2e",
|
||||
"integration"
|
||||
],
|
||||
"requiredTags": [
|
||||
"exception",
|
||||
"recovery",
|
||||
"context-retention"
|
||||
],
|
||||
"requiredEvidence": [
|
||||
"playwright-trace",
|
||||
"db-assertions"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"exception-first",
|
||||
"detail-context-retention",
|
||||
"retryable-vs-terminal",
|
||||
"partial-action-result"
|
||||
]
|
||||
}
|
||||
},
|
||||
"T07": {
|
||||
"code": "T07",
|
||||
"type": "reconcile",
|
||||
"templateComponent": "KbxReconcilePage",
|
||||
"defaultCommands": [
|
||||
{
|
||||
"id": "search",
|
||||
"label": "조회",
|
||||
"group": "query",
|
||||
"shortcut": "F3",
|
||||
"permissionKind": "none"
|
||||
}
|
||||
],
|
||||
"requiredPolicies": [
|
||||
"expected-actual-difference-projection",
|
||||
"reason-code",
|
||||
"resolution-state",
|
||||
"audit"
|
||||
],
|
||||
"recoveryPolicies": [
|
||||
"grace-period-before-mismatch",
|
||||
"mismatch-only-filter",
|
||||
"resolution-retry",
|
||||
"retain-comparison-context"
|
||||
],
|
||||
"securityPolicies": [
|
||||
"screen-permission",
|
||||
"resolution-permission",
|
||||
"server-enforcement"
|
||||
],
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.common.reconcile.grace-period",
|
||||
"scenario.common.reconcile.mismatch-recovery"
|
||||
],
|
||||
"scaffoldSurfaces": [
|
||||
"search",
|
||||
"content",
|
||||
"resolution"
|
||||
],
|
||||
"testProfile": {
|
||||
"requiredScenarioKinds": [
|
||||
"e2e",
|
||||
"integration"
|
||||
],
|
||||
"requiredTags": [
|
||||
"reconcile",
|
||||
"mismatch-filter",
|
||||
"eventual-consistency"
|
||||
],
|
||||
"requiredEvidence": [
|
||||
"playwright-trace",
|
||||
"db-assertions"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"mismatch-only-filter",
|
||||
"grace-period",
|
||||
"resolution-retry",
|
||||
"comparison-context"
|
||||
]
|
||||
}
|
||||
},
|
||||
"T08": {
|
||||
"code": "T08",
|
||||
"type": "import",
|
||||
"templateComponent": "KbxImportPage",
|
||||
"defaultCommands": [],
|
||||
"requiredPolicies": [
|
||||
"staging-before-domain-write",
|
||||
"mapping-source-traceability",
|
||||
"background-job-threshold",
|
||||
"idempotent-commit",
|
||||
"audit"
|
||||
],
|
||||
"recoveryPolicies": [
|
||||
"session-mapping-isolation",
|
||||
"validation-error-download",
|
||||
"partial-commit-result",
|
||||
"job-refresh-recovery"
|
||||
],
|
||||
"securityPolicies": [
|
||||
"screen-permission",
|
||||
"file-preflight",
|
||||
"commit-permission",
|
||||
"server-validation",
|
||||
"sensitive-column-policy"
|
||||
],
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.oms.order-import.partial"
|
||||
],
|
||||
"scaffoldSurfaces": [
|
||||
"steps",
|
||||
"content",
|
||||
"result"
|
||||
],
|
||||
"testProfile": {
|
||||
"requiredScenarioKinds": [
|
||||
"e2e"
|
||||
],
|
||||
"requiredTags": [
|
||||
"excel",
|
||||
"mapping",
|
||||
"staging",
|
||||
"partial-success",
|
||||
"job"
|
||||
],
|
||||
"requiredEvidence": [
|
||||
"playwright-trace",
|
||||
"problem-json"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"mapping-isolation",
|
||||
"validation-download",
|
||||
"commit-confirm",
|
||||
"job-refresh-recovery"
|
||||
]
|
||||
}
|
||||
},
|
||||
"T09": {
|
||||
"code": "T09",
|
||||
"type": "wms-mobile",
|
||||
"templateComponent": "KbxWmsMobilePage",
|
||||
"defaultCommands": [],
|
||||
"requiredPolicies": [
|
||||
"barcode-normalization",
|
||||
"server-validation-before-success",
|
||||
"idempotent-scan-command",
|
||||
"network-state",
|
||||
"offline-command-policy"
|
||||
],
|
||||
"recoveryPolicies": [
|
||||
"duplicate-scan-debounce",
|
||||
"response-loss-replay",
|
||||
"wrong-item-no-retry",
|
||||
"pending-command-visibility"
|
||||
],
|
||||
"securityPolicies": [
|
||||
"screen-permission",
|
||||
"execute-permission",
|
||||
"server-enforcement",
|
||||
"offline-command-allowlist"
|
||||
],
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.wms.picking.idempotent-replay",
|
||||
"scenario.wms.picking.wrong-item"
|
||||
],
|
||||
"scaffoldSurfaces": [
|
||||
"context",
|
||||
"content",
|
||||
"actions"
|
||||
],
|
||||
"testProfile": {
|
||||
"requiredScenarioKinds": [
|
||||
"e2e"
|
||||
],
|
||||
"requiredTags": [
|
||||
"scanner",
|
||||
"idempotency",
|
||||
"network",
|
||||
"retry-policy"
|
||||
],
|
||||
"requiredEvidence": [
|
||||
"playwright-trace",
|
||||
"api-transcript"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"scan-normalization",
|
||||
"server-before-success",
|
||||
"response-loss-replay",
|
||||
"wrong-item-no-retry"
|
||||
]
|
||||
}
|
||||
}
|
||||
} as const satisfies Record<string,KbxScreenRecipeDefinition>
|
||||
export const kbxScreenRecipeVerificationCatalog={
|
||||
"T01": {
|
||||
"code": "T01",
|
||||
"type": "list",
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.oms.order-list.bulk-ship",
|
||||
"scenario.oms.order-list.all-filtered-ship"
|
||||
],
|
||||
"scenarioKinds": [
|
||||
"contract",
|
||||
"e2e"
|
||||
],
|
||||
"tags": [
|
||||
"all-filtered",
|
||||
"audit",
|
||||
"bulk",
|
||||
"filter-snapshot",
|
||||
"golden-screen",
|
||||
"idempotency",
|
||||
"outbox"
|
||||
],
|
||||
"evidence": [
|
||||
"api-transcript",
|
||||
"correlation-ids",
|
||||
"db-assertions",
|
||||
"playwright-trace",
|
||||
"screenshot",
|
||||
"vitest-contract"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"idle-search",
|
||||
"refresh-retains-context",
|
||||
"bulk-partial-result",
|
||||
"safe-drilldown"
|
||||
],
|
||||
"missingScenarioKinds": [],
|
||||
"missingTags": [],
|
||||
"missingEvidence": [],
|
||||
"complete": true
|
||||
},
|
||||
"T02": {
|
||||
"code": "T02",
|
||||
"type": "master",
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.erp.item-master.lifecycle",
|
||||
"scenario.erp.item-master.keyboard-recovery"
|
||||
],
|
||||
"scenarioKinds": [
|
||||
"e2e",
|
||||
"integration"
|
||||
],
|
||||
"tags": [
|
||||
"audit",
|
||||
"concurrency",
|
||||
"golden-screen",
|
||||
"keyboard",
|
||||
"master-crud",
|
||||
"permission",
|
||||
"recovery",
|
||||
"state-policy"
|
||||
],
|
||||
"evidence": [
|
||||
"api-transcript",
|
||||
"db-assertions",
|
||||
"playwright-trace",
|
||||
"problem-json",
|
||||
"screenshot"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"permission-aware-save",
|
||||
"dirty-guard",
|
||||
"conflict-reload",
|
||||
"audit-visible"
|
||||
],
|
||||
"missingScenarioKinds": [],
|
||||
"missingTags": [],
|
||||
"missingEvidence": [],
|
||||
"complete": true
|
||||
},
|
||||
"T03": {
|
||||
"code": "T03",
|
||||
"type": "transaction",
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.oms.order-register.keyboard",
|
||||
"scenario.oms.order-register.conflict",
|
||||
"scenario.oms.order-register.lifecycle"
|
||||
],
|
||||
"scenarioKinds": [
|
||||
"e2e",
|
||||
"integration"
|
||||
],
|
||||
"tags": [
|
||||
"audit",
|
||||
"concurrency",
|
||||
"conflict",
|
||||
"golden-screen",
|
||||
"keyboard",
|
||||
"lookup",
|
||||
"recovery",
|
||||
"state-policy",
|
||||
"transaction",
|
||||
"validation",
|
||||
"workflow"
|
||||
],
|
||||
"evidence": [
|
||||
"api-transcript",
|
||||
"db-assertions",
|
||||
"playwright-trace",
|
||||
"problem-json",
|
||||
"screenshot"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"f2-lookup",
|
||||
"f8-save",
|
||||
"row-key-validation",
|
||||
"conflict-recovery"
|
||||
],
|
||||
"missingScenarioKinds": [],
|
||||
"missingTags": [],
|
||||
"missingEvidence": [],
|
||||
"complete": true
|
||||
},
|
||||
"T04": {
|
||||
"code": "T04",
|
||||
"type": "fast-entry",
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.erp.item-price.fast-entry",
|
||||
"scenario.oms.order-register.fast-entry"
|
||||
],
|
||||
"scenarioKinds": [
|
||||
"contract",
|
||||
"e2e"
|
||||
],
|
||||
"tags": [
|
||||
"audit",
|
||||
"fast-entry",
|
||||
"fill-down",
|
||||
"golden-screen",
|
||||
"idempotency",
|
||||
"inline-validation",
|
||||
"lookup",
|
||||
"outbox",
|
||||
"paste"
|
||||
],
|
||||
"evidence": [
|
||||
"api-transcript",
|
||||
"component-catalog",
|
||||
"db-assertions",
|
||||
"playwright-trace",
|
||||
"problem-json",
|
||||
"vitest-contract"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"multi-cell-paste",
|
||||
"fill-down",
|
||||
"error-navigation",
|
||||
"partial-save-result"
|
||||
],
|
||||
"missingScenarioKinds": [],
|
||||
"missingTags": [],
|
||||
"missingEvidence": [],
|
||||
"complete": true
|
||||
},
|
||||
"T05": {
|
||||
"code": "T05",
|
||||
"type": "master-detail",
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.erp.inventory.master-detail-context"
|
||||
],
|
||||
"scenarioKinds": [
|
||||
"e2e"
|
||||
],
|
||||
"tags": [
|
||||
"context-retention",
|
||||
"drill-down",
|
||||
"golden-screen",
|
||||
"history",
|
||||
"master-detail"
|
||||
],
|
||||
"evidence": [
|
||||
"api-transcript",
|
||||
"playwright-trace",
|
||||
"screenshot"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"master-selection-context",
|
||||
"detail-error-retains-master",
|
||||
"history-context",
|
||||
"safe-drilldown"
|
||||
],
|
||||
"missingScenarioKinds": [],
|
||||
"missingTags": [],
|
||||
"missingEvidence": [],
|
||||
"complete": true
|
||||
},
|
||||
"T06": {
|
||||
"code": "T06",
|
||||
"type": "queue",
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.common.operations.stale-event",
|
||||
"scenario.integration.manual-retry.idempotent",
|
||||
"scenario.common.operations.queue-recovery"
|
||||
],
|
||||
"scenarioKinds": [
|
||||
"e2e",
|
||||
"integration"
|
||||
],
|
||||
"tags": [
|
||||
"context-retention",
|
||||
"exception",
|
||||
"golden-screen",
|
||||
"idempotency",
|
||||
"integration",
|
||||
"manual-retry",
|
||||
"ordering",
|
||||
"outbox",
|
||||
"permission",
|
||||
"projection",
|
||||
"queue",
|
||||
"recovery"
|
||||
],
|
||||
"evidence": [
|
||||
"api-transcript",
|
||||
"correlation-ids",
|
||||
"db-assertions",
|
||||
"playwright-trace",
|
||||
"projection-event-log",
|
||||
"screenshot"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"exception-first",
|
||||
"detail-context-retention",
|
||||
"retryable-vs-terminal",
|
||||
"partial-action-result"
|
||||
],
|
||||
"missingScenarioKinds": [],
|
||||
"missingTags": [],
|
||||
"missingEvidence": [],
|
||||
"complete": true
|
||||
},
|
||||
"T07": {
|
||||
"code": "T07",
|
||||
"type": "reconcile",
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.common.reconcile.grace-period",
|
||||
"scenario.common.reconcile.mismatch-recovery"
|
||||
],
|
||||
"scenarioKinds": [
|
||||
"e2e",
|
||||
"integration"
|
||||
],
|
||||
"tags": [
|
||||
"context-retention",
|
||||
"eventual-consistency",
|
||||
"golden-screen",
|
||||
"mismatch-filter",
|
||||
"reconcile",
|
||||
"recovery"
|
||||
],
|
||||
"evidence": [
|
||||
"api-transcript",
|
||||
"clock-snapshot",
|
||||
"db-assertions",
|
||||
"playwright-trace",
|
||||
"screenshot"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"mismatch-only-filter",
|
||||
"grace-period",
|
||||
"resolution-retry",
|
||||
"comparison-context"
|
||||
],
|
||||
"missingScenarioKinds": [],
|
||||
"missingTags": [],
|
||||
"missingEvidence": [],
|
||||
"complete": true
|
||||
},
|
||||
"T08": {
|
||||
"code": "T08",
|
||||
"type": "import",
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.oms.order-import.partial"
|
||||
],
|
||||
"scenarioKinds": [
|
||||
"e2e"
|
||||
],
|
||||
"tags": [
|
||||
"excel",
|
||||
"job",
|
||||
"mapping",
|
||||
"partial-success",
|
||||
"staging"
|
||||
],
|
||||
"evidence": [
|
||||
"api-transcript",
|
||||
"db-assertions",
|
||||
"error-workbook-metadata",
|
||||
"import-session-snapshot",
|
||||
"playwright-trace",
|
||||
"problem-json"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"mapping-isolation",
|
||||
"validation-download",
|
||||
"commit-confirm",
|
||||
"job-refresh-recovery"
|
||||
],
|
||||
"missingScenarioKinds": [],
|
||||
"missingTags": [],
|
||||
"missingEvidence": [],
|
||||
"complete": true
|
||||
},
|
||||
"T09": {
|
||||
"code": "T09",
|
||||
"type": "wms-mobile",
|
||||
"canonicalScenarioIds": [
|
||||
"scenario.wms.picking.idempotent-replay",
|
||||
"scenario.wms.picking.wrong-item"
|
||||
],
|
||||
"scenarioKinds": [
|
||||
"e2e"
|
||||
],
|
||||
"tags": [
|
||||
"business-error",
|
||||
"golden-screen",
|
||||
"idempotency",
|
||||
"network",
|
||||
"retry-policy",
|
||||
"scanner"
|
||||
],
|
||||
"evidence": [
|
||||
"api-transcript",
|
||||
"db-assertions",
|
||||
"playwright-trace",
|
||||
"scanner-event-log"
|
||||
],
|
||||
"requiredChecks": [
|
||||
"scan-normalization",
|
||||
"server-before-success",
|
||||
"response-loss-replay",
|
||||
"wrong-item-no-retry"
|
||||
],
|
||||
"missingScenarioKinds": [],
|
||||
"missingTags": [],
|
||||
"missingEvidence": [],
|
||||
"complete": true
|
||||
}
|
||||
} as const
|
||||
+284
@@ -0,0 +1,284 @@
|
||||
// generated from contracts/telemetry/kbx.telemetry.json; do not edit.
|
||||
export const kbxTelemetryCatalog = {
|
||||
"screen.open": {
|
||||
"name": "screen.open",
|
||||
"category": "navigation",
|
||||
"description": "화면 진입",
|
||||
"allowedAttributes": [
|
||||
"module",
|
||||
"launchMode"
|
||||
]
|
||||
},
|
||||
"screen.close": {
|
||||
"name": "screen.close",
|
||||
"category": "navigation",
|
||||
"description": "화면 종료",
|
||||
"allowedAttributes": [
|
||||
"module",
|
||||
"closeReason"
|
||||
]
|
||||
},
|
||||
"task.start": {
|
||||
"name": "task.start",
|
||||
"category": "task",
|
||||
"description": "측정 가능한 업무 Task 시작",
|
||||
"allowedAttributes": [
|
||||
"taskType"
|
||||
]
|
||||
},
|
||||
"task.complete": {
|
||||
"name": "task.complete",
|
||||
"category": "task",
|
||||
"description": "업무 Task 정상 완료",
|
||||
"allowedAttributes": [
|
||||
"taskType",
|
||||
"result"
|
||||
],
|
||||
"requiresDuration": true
|
||||
},
|
||||
"task.abandon": {
|
||||
"name": "task.abandon",
|
||||
"category": "task",
|
||||
"description": "업무 Task 중단",
|
||||
"allowedAttributes": [
|
||||
"taskType",
|
||||
"reasonCode"
|
||||
],
|
||||
"requiresDuration": true
|
||||
},
|
||||
"interaction.execute": {
|
||||
"name": "interaction.execute",
|
||||
"category": "interaction",
|
||||
"description": "KBX 의미 단위 업무 조작 실행",
|
||||
"allowedAttributes": [
|
||||
"interactionType",
|
||||
"commandId"
|
||||
]
|
||||
},
|
||||
"search.execute": {
|
||||
"name": "search.execute",
|
||||
"category": "interaction",
|
||||
"description": "조회 실행",
|
||||
"allowedAttributes": [
|
||||
"resultBucket"
|
||||
]
|
||||
},
|
||||
"command.execute": {
|
||||
"name": "command.execute",
|
||||
"category": "command",
|
||||
"description": "업무 Command 실행 시도",
|
||||
"allowedAttributes": [
|
||||
"commandId",
|
||||
"operationKind"
|
||||
]
|
||||
},
|
||||
"command.succeeded": {
|
||||
"name": "command.succeeded",
|
||||
"category": "command",
|
||||
"description": "업무 Command 성공",
|
||||
"allowedAttributes": [
|
||||
"commandId",
|
||||
"operationKind"
|
||||
],
|
||||
"requiresDuration": true
|
||||
},
|
||||
"command.failed": {
|
||||
"name": "command.failed",
|
||||
"category": "command",
|
||||
"description": "업무 Command 실패",
|
||||
"allowedAttributes": [
|
||||
"commandId",
|
||||
"problemType",
|
||||
"reasonCode"
|
||||
],
|
||||
"requiresDuration": true
|
||||
},
|
||||
"lookup.open": {
|
||||
"name": "lookup.open",
|
||||
"category": "lookup",
|
||||
"description": "Lookup 열기",
|
||||
"allowedAttributes": [
|
||||
"entityType"
|
||||
]
|
||||
},
|
||||
"lookup.select": {
|
||||
"name": "lookup.select",
|
||||
"category": "lookup",
|
||||
"description": "Lookup 선택 완료",
|
||||
"allowedAttributes": [
|
||||
"entityType",
|
||||
"selectionSource"
|
||||
]
|
||||
},
|
||||
"grid.bulk_action": {
|
||||
"name": "grid.bulk_action",
|
||||
"category": "interaction",
|
||||
"description": "Grid 일괄처리 실행",
|
||||
"allowedAttributes": [
|
||||
"commandId",
|
||||
"countBucket"
|
||||
]
|
||||
},
|
||||
"validation.failed": {
|
||||
"name": "validation.failed",
|
||||
"category": "quality",
|
||||
"description": "저장/업무 실행 전후 검증 실패",
|
||||
"allowedAttributes": [
|
||||
"stage",
|
||||
"errorCountBucket",
|
||||
"reasonCode"
|
||||
]
|
||||
},
|
||||
"excel.import.start": {
|
||||
"name": "excel.import.start",
|
||||
"category": "excel",
|
||||
"description": "Excel Import 시작",
|
||||
"allowedAttributes": [
|
||||
"importType",
|
||||
"rowCountBucket"
|
||||
]
|
||||
},
|
||||
"excel.import.completed": {
|
||||
"name": "excel.import.completed",
|
||||
"category": "excel",
|
||||
"description": "Excel Import 완료",
|
||||
"allowedAttributes": [
|
||||
"importType",
|
||||
"result",
|
||||
"rowCountBucket"
|
||||
],
|
||||
"requiresDuration": true
|
||||
},
|
||||
"excel.import.failed": {
|
||||
"name": "excel.import.failed",
|
||||
"category": "excel",
|
||||
"description": "Excel Import 실패",
|
||||
"allowedAttributes": [
|
||||
"importType",
|
||||
"reasonCode",
|
||||
"rowCountBucket"
|
||||
],
|
||||
"requiresDuration": true
|
||||
},
|
||||
"exception.open": {
|
||||
"name": "exception.open",
|
||||
"category": "exception",
|
||||
"description": "업무 예외 생성/노출",
|
||||
"allowedAttributes": [
|
||||
"exceptionType",
|
||||
"severity"
|
||||
]
|
||||
},
|
||||
"exception.resolved": {
|
||||
"name": "exception.resolved",
|
||||
"category": "exception",
|
||||
"description": "업무 예외 해결",
|
||||
"allowedAttributes": [
|
||||
"exceptionType",
|
||||
"resolutionType"
|
||||
],
|
||||
"requiresDuration": true
|
||||
},
|
||||
"ai.proposal.open": {
|
||||
"name": "ai.proposal.open",
|
||||
"category": "ai",
|
||||
"description": "AI 제안 확인",
|
||||
"allowedAttributes": [
|
||||
"proposalType"
|
||||
]
|
||||
},
|
||||
"ai.proposal.accept": {
|
||||
"name": "ai.proposal.accept",
|
||||
"category": "ai",
|
||||
"description": "AI 제안 승인",
|
||||
"allowedAttributes": [
|
||||
"proposalType"
|
||||
]
|
||||
},
|
||||
"ai.proposal.reject": {
|
||||
"name": "ai.proposal.reject",
|
||||
"category": "ai",
|
||||
"description": "AI 제안 거절",
|
||||
"allowedAttributes": [
|
||||
"proposalType",
|
||||
"reasonCode"
|
||||
]
|
||||
},
|
||||
"manual.intervention": {
|
||||
"name": "manual.intervention",
|
||||
"category": "outcome",
|
||||
"description": "정상 자동처리 대신 사람의 확인/수정/판단이 필요했던 업무",
|
||||
"allowedAttributes": [
|
||||
"workType",
|
||||
"reasonCode",
|
||||
"exceptionType"
|
||||
]
|
||||
},
|
||||
"experiment.exposed": {
|
||||
"name": "experiment.exposed",
|
||||
"category": "experiment",
|
||||
"description": "실험 Variant가 실제 화면에 렌더링되어 사용자에게 노출됨",
|
||||
"allowedAttributes": [
|
||||
"surface"
|
||||
]
|
||||
}
|
||||
} as const
|
||||
export type KbxTelemetryEventName = keyof typeof kbxTelemetryCatalog
|
||||
export const kbxUxMetricCatalog = {
|
||||
"task_completion_time_ms": {
|
||||
"key": "task_completion_time_ms",
|
||||
"label": "Task Completion Time",
|
||||
"numerator": "task.complete.duration_ms",
|
||||
"aggregation": "p50,p95",
|
||||
"unit": "ms"
|
||||
},
|
||||
"semantic_interactions_per_task": {
|
||||
"key": "semantic_interactions_per_task",
|
||||
"label": "Interactions / Task",
|
||||
"numerator": "interaction.execute",
|
||||
"denominator": "task.complete",
|
||||
"aggregation": "ratio",
|
||||
"unit": "count"
|
||||
},
|
||||
"manual_intervention_rate": {
|
||||
"key": "manual_intervention_rate",
|
||||
"label": "Manual Intervention Rate",
|
||||
"numerator": "ux_business_outcomes.manual_intervention_count",
|
||||
"denominator": "ux_business_outcomes.observed_count",
|
||||
"aggregation": "ratio",
|
||||
"unit": "percent"
|
||||
},
|
||||
"validation_failure_rate": {
|
||||
"key": "validation_failure_rate",
|
||||
"label": "Validation Failure Rate",
|
||||
"numerator": "validation.failed",
|
||||
"denominator": "command.execute",
|
||||
"aggregation": "ratio",
|
||||
"unit": "percent"
|
||||
},
|
||||
"import_failure_rate": {
|
||||
"key": "import_failure_rate",
|
||||
"label": "Import Failure Rate",
|
||||
"numerator": "excel.import.failed",
|
||||
"denominator": "excel.import.start",
|
||||
"aggregation": "ratio",
|
||||
"unit": "percent"
|
||||
},
|
||||
"exception_resolution_time_ms": {
|
||||
"key": "exception_resolution_time_ms",
|
||||
"label": "Exception Resolution Time",
|
||||
"numerator": "exception.resolved.duration_ms",
|
||||
"aggregation": "p50,p95",
|
||||
"unit": "ms"
|
||||
},
|
||||
"ai_proposal_acceptance_rate": {
|
||||
"key": "ai_proposal_acceptance_rate",
|
||||
"label": "AI Proposal Acceptance Rate",
|
||||
"numerator": "ai.proposal.accept",
|
||||
"denominator": "ai.proposal.open",
|
||||
"aggregation": "ratio",
|
||||
"unit": "percent"
|
||||
}
|
||||
} as const
|
||||
export type KbxUxMetricKey = keyof typeof kbxUxMetricCatalog
|
||||
export const kbxTelemetrySourceSha256 = '9f5de69498b657cb0d60df18c1e98c504a44eec555c4fc50d46f15f83a4ea1ce' as const
|
||||
+2139
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
import type { KbxLookupDefinition } from './lookup'
|
||||
|
||||
export type KbxGridType =
|
||||
| 'text' | 'code' | 'integer' | 'decimal' | 'quantity' | 'money'
|
||||
| 'percent' | 'date' | 'datetime' | 'boolean' | 'status' | 'lookup' | 'link'
|
||||
|
||||
export type KbxGridDensity = 'compact' | 'comfortable'
|
||||
|
||||
export interface KbxGridColumn<T> {
|
||||
field: keyof T & string
|
||||
header: string
|
||||
type?: KbxGridType
|
||||
width?: number
|
||||
minWidth?: number
|
||||
maxWidth?: number
|
||||
pinned?: 'left' | 'right'
|
||||
editable?: boolean | ((row: T) => boolean)
|
||||
sortable?: boolean
|
||||
filterable?: boolean
|
||||
permission?: string
|
||||
lookup?: KbxLookupDefinition
|
||||
drilldown?: boolean
|
||||
}
|
||||
|
||||
export interface KbxGridColumnPreference {
|
||||
field: string
|
||||
order: number
|
||||
width?: number
|
||||
pinned?: 'left' | 'right' | null
|
||||
hidden?: boolean
|
||||
sort?: 'asc' | 'desc' | null
|
||||
sortIndex?: number | null
|
||||
}
|
||||
|
||||
export interface KbxGridCellRef<T = string> {
|
||||
rowKey: T
|
||||
field: string
|
||||
}
|
||||
|
||||
export interface KbxGridSummary<T> {
|
||||
key: string
|
||||
label: string
|
||||
field?: keyof T & string
|
||||
kind: 'count' | 'sum' | 'custom'
|
||||
value?: string | number
|
||||
}
|
||||
|
||||
/** Browser에는 현재 선택 상태만 유지한다. all-filtered에서 전체 ID를 적재하지 않는다. */
|
||||
export interface KbxSelectionState<TId = string> {
|
||||
mode: 'explicit' | 'all-filtered'
|
||||
selectedIds: TId[]
|
||||
excludedIds?: TId[]
|
||||
}
|
||||
|
||||
/** Server-side bulk command의 canonical selection envelope. */
|
||||
export interface KbxBulkSelectionRequest<TFilter = Record<string, unknown>, TId = string> {
|
||||
mode: 'ids' | 'filter'
|
||||
ids?: TId[]
|
||||
filter?: TFilter
|
||||
excludedIds?: TId[]
|
||||
}
|
||||
|
||||
export interface KbxGridEditingPolicy {
|
||||
allowRowAdd?: boolean
|
||||
allowRowDuplicate?: boolean
|
||||
fillDown?: boolean
|
||||
paste?: boolean
|
||||
errorNavigation?: boolean
|
||||
}
|
||||
|
||||
export interface KbxGridPasteIssue {
|
||||
rowOffset: number
|
||||
columnOffset: number
|
||||
field?: string
|
||||
code: 'INVALID_NUMBER' | 'INVALID_DATE' | 'INVALID_BOOLEAN'
|
||||
value: unknown
|
||||
}
|
||||
|
||||
export interface KbxGridPasteResult {
|
||||
cellCount: number
|
||||
normalizedCount: number
|
||||
rejectedCount: number
|
||||
issues: KbxGridPasteIssue[]
|
||||
}
|
||||
|
||||
export interface KbxGridContextRequest<T> {
|
||||
row: T
|
||||
field: keyof T & string
|
||||
clientX: number
|
||||
clientY: number
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export interface KbxHelpContent {
|
||||
key: string
|
||||
title: string
|
||||
purpose: string
|
||||
steps?: string[]
|
||||
shortcuts?: { key: string; description: string }[]
|
||||
cautions?: string[]
|
||||
relatedScreens?: { id: string; title: string }[]
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
export * from './screen'
|
||||
export * from './ui'
|
||||
export * from './command'
|
||||
export * from './grid'
|
||||
export * from './lookup'
|
||||
export * from './problem'
|
||||
|
||||
export * from './field'
|
||||
export * from './transaction'
|
||||
export * from './audit'
|
||||
|
||||
export * from './wms'
|
||||
export * from './registry'
|
||||
export * from './permission'
|
||||
export * from './help'
|
||||
export * from './preference'
|
||||
export * from './status'
|
||||
export * from './search'
|
||||
export * from './excel'
|
||||
|
||||
export * from './operations'
|
||||
export * from './suggestion'
|
||||
export * from './ai'
|
||||
export * from './workflow'
|
||||
export * from './runtime'
|
||||
export * from './performance'
|
||||
export * from './navigation'
|
||||
|
||||
export * from './catalog'
|
||||
|
||||
export * from './generated/fieldCatalog'
|
||||
|
||||
export * from './api'
|
||||
|
||||
export * from './generated/apiCatalog'
|
||||
export * from './authorization'
|
||||
export * from './generated/permissionCatalog'
|
||||
|
||||
export * from './telemetry'
|
||||
export * from './generated/telemetryCatalog'
|
||||
|
||||
export * from './experiment'
|
||||
export * from './generated/experimentCatalog'
|
||||
|
||||
export * from './testing'
|
||||
export * from './generated/testScenarioCatalog'
|
||||
export * from './generated/screenRecipeCatalog'
|
||||
|
||||
export * from './integration'
|
||||
export * from './generated/integrationCatalog'
|
||||
|
||||
export * from './provider'
|
||||
export * from './generated/providerCatalog'
|
||||
|
||||
export * from './externalData'
|
||||
export * from './generated/externalDataCatalog'
|
||||
|
||||
export * from './configuration'
|
||||
export * from './generated/configurationCatalog'
|
||||
@@ -0,0 +1,58 @@
|
||||
export type KbxIntegrationState = 'queued' | 'delivering' | 'retrying' | 'delivered' | 'failed' | 'suspended'
|
||||
export type KbxIntegrationDirection = 'inbound' | 'outbound'
|
||||
export type KbxIntegrationTransport = 'outbox-http' | 'outbox-event' | 'inbox-event'
|
||||
export type KbxIntegrationDelivery = 'at-most-once' | 'at-least-once'
|
||||
export type KbxIntegrationCriticality = 'low' | 'medium' | 'high'
|
||||
|
||||
export interface KbxIntegrationShortRetryDefinition {
|
||||
maxRetryAttempts: number
|
||||
baseDelayMs: number
|
||||
backoff: 'constant' | 'exponential'
|
||||
}
|
||||
|
||||
export interface KbxIntegrationLongRetryDefinition {
|
||||
scheduler: 'hangfire'
|
||||
maxAttempts: number
|
||||
scheduleSeconds: readonly number[]
|
||||
}
|
||||
|
||||
export interface KbxIntegrationCircuitBreakerDefinition {
|
||||
failureRatio: number
|
||||
samplingSeconds: number
|
||||
minimumThroughput: number
|
||||
breakSeconds: number
|
||||
}
|
||||
|
||||
export interface KbxIntegrationDefinition {
|
||||
id: string
|
||||
title: string
|
||||
ownerModule: 'OMS' | 'ERP' | 'WMS' | 'COMMON'
|
||||
direction: KbxIntegrationDirection
|
||||
transport: KbxIntegrationTransport
|
||||
criticality: KbxIntegrationCriticality
|
||||
sourceEvent: string
|
||||
target: string
|
||||
delivery: KbxIntegrationDelivery
|
||||
ordering: 'none' | 'per-aggregate'
|
||||
idempotency: 'none' | 'event-id' | 'business-key'
|
||||
timeoutMs: number
|
||||
shortRetry: KbxIntegrationShortRetryDefinition
|
||||
longRetry: KbxIntegrationLongRetryDefinition
|
||||
circuitBreaker: KbxIntegrationCircuitBreakerDefinition
|
||||
retryable: readonly string[]
|
||||
permanent: readonly string[]
|
||||
terminalAction: 'operations-exception' | 'dead-letter'
|
||||
userVisible: boolean
|
||||
}
|
||||
|
||||
export interface KbxIntegrationStatusView {
|
||||
integrationId: string
|
||||
state: KbxIntegrationState
|
||||
label: string
|
||||
attemptCount?: number
|
||||
lastAttemptAt?: string
|
||||
nextRetryAt?: string
|
||||
detail?: string
|
||||
correlationId?: string
|
||||
retryAllowed?: boolean
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
export type KbxLookupColumnSource =
|
||||
| 'code'
|
||||
| 'displayName'
|
||||
| 'secondaryText'
|
||||
| 'status'
|
||||
| `metadata.${string}`
|
||||
|
||||
export interface KbxLookupColumnDefinition {
|
||||
key: string
|
||||
label: string
|
||||
source: KbxLookupColumnSource
|
||||
width?: number
|
||||
align?: 'left' | 'center' | 'right'
|
||||
}
|
||||
|
||||
export interface KbxLookupDefinition {
|
||||
entity: string
|
||||
columns?: KbxLookupColumnDefinition[]
|
||||
pageSize?: number
|
||||
}
|
||||
|
||||
export interface KbxLookupItem<TId = string> {
|
||||
id: TId
|
||||
code: string
|
||||
displayName: string
|
||||
secondaryText?: string
|
||||
status?: string
|
||||
metadata?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export interface KbxLookupSearchRequest {
|
||||
query?: string
|
||||
page: number
|
||||
pageSize: number
|
||||
filters?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export interface KbxLookupSearchResult<TId = string> {
|
||||
items: KbxLookupItem<TId>[]
|
||||
totalCount: number
|
||||
}
|
||||
|
||||
export interface KbxLookupProvider<TId = string> {
|
||||
search(request: KbxLookupSearchRequest): Promise<KbxLookupSearchResult<TId>>
|
||||
resolveById(id: TId): Promise<KbxLookupItem<TId> | null>
|
||||
resolveByCode(code: string): Promise<KbxLookupItem<TId> | null>
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
export type KbxWorkspaceLaunchMode = 'tab' | 'replace' | 'external'
|
||||
export type KbxRecentPolicy = 'screen' | 'route' | 'none'
|
||||
|
||||
export interface KbxNavigationEntry {
|
||||
screenId: string
|
||||
path: string
|
||||
section: string
|
||||
group?: string
|
||||
keywords?: string[]
|
||||
order?: number
|
||||
launchMode?: KbxWorkspaceLaunchMode
|
||||
menuVisible?: boolean
|
||||
favoriteAllowed?: boolean
|
||||
/** Persist only a safe catalog path by default. Route mode is opt-in for non-sensitive parameterized routes. */
|
||||
recentPolicy?: KbxRecentPolicy
|
||||
/** Menu discovery can be narrower than direct screen access. */
|
||||
permissions?: string[]
|
||||
/** Lower values are surfaced first in Home quick-start. Omit when the screen should not be promoted. */
|
||||
homePriority?: number
|
||||
/** Stable business-oriented group used by Home without inventing dashboard categories. */
|
||||
homeGroup?: string
|
||||
}
|
||||
|
||||
export interface KbxNavigationResolvedEntry extends KbxNavigationEntry {
|
||||
title: string
|
||||
module: 'OMS' | 'ERP' | 'WMS' | 'COMMON'
|
||||
permissions?: string[]
|
||||
}
|
||||
|
||||
export interface KbxNavigationSection {
|
||||
key: string
|
||||
label: string
|
||||
module?: 'OMS' | 'ERP' | 'WMS' | 'COMMON'
|
||||
entries: KbxNavigationResolvedEntry[]
|
||||
}
|
||||
|
||||
export interface KbxRecentNavigation {
|
||||
screenId: string
|
||||
path: string
|
||||
title: string
|
||||
visitedAt: string
|
||||
}
|
||||
|
||||
export interface KbxWorkspaceTab {
|
||||
key: string
|
||||
screenId: string
|
||||
title: string
|
||||
path: string
|
||||
dirty?: boolean
|
||||
pinned?: boolean
|
||||
openedAt: string
|
||||
lastActivatedAt: string
|
||||
}
|
||||
|
||||
export interface KbxNavigationPreference {
|
||||
favorites: string[]
|
||||
recents: KbxRecentNavigation[]
|
||||
sideNavCollapsed: boolean
|
||||
workspaceMaxTabs: number
|
||||
/** Versioned key used to prevent cross-user/tenant preference leakage. */
|
||||
scopeKey?: string
|
||||
}
|
||||
|
||||
|
||||
export type KbxHomeLaunchSource = 'dirty' | 'pinned' | 'open' | 'favorite' | 'recent' | 'priority'
|
||||
|
||||
export interface KbxHomeLaunchItem {
|
||||
/** Stable UI key. Open workspace instances use tabKey so multiple records from one screen can coexist. */
|
||||
launchKey: string
|
||||
screenId: string
|
||||
title: string
|
||||
module: 'OMS' | 'ERP' | 'WMS' | 'COMMON'
|
||||
section: string
|
||||
path: string
|
||||
source: KbxHomeLaunchSource
|
||||
sourceLabel: string
|
||||
tabKey?: string
|
||||
/** Optional human-readable route instance hint for multiple open records of the same screen. */
|
||||
instanceLabel?: string
|
||||
homeGroup?: string
|
||||
}
|
||||
|
||||
|
||||
export type KbxHomeAttentionSource = 'dirty' | 'operation-failed' | 'notification-urgent' | 'operation-running' | 'notification'
|
||||
|
||||
export interface KbxHomeAttentionItem {
|
||||
key: string
|
||||
source: KbxHomeAttentionSource
|
||||
priority: number
|
||||
/** Used for deterministic newest-first ordering inside the same business priority. */
|
||||
occurredAt: string
|
||||
title: string
|
||||
detail?: string
|
||||
actionLabel: string
|
||||
screenId?: string
|
||||
path?: string
|
||||
tabKey?: string
|
||||
operationId?: string
|
||||
notificationId?: string
|
||||
}
|
||||
|
||||
export interface KbxHomeAttentionQueue {
|
||||
items: KbxHomeAttentionItem[]
|
||||
totalCount: number
|
||||
overflowCount: number
|
||||
sourceCounts: Partial<Record<KbxHomeAttentionSource, number>>
|
||||
}
|
||||
|
||||
export interface KbxMenuSearchResult {
|
||||
screenId: string
|
||||
title: string
|
||||
module: 'OMS' | 'ERP' | 'WMS' | 'COMMON'
|
||||
section: string
|
||||
path: string
|
||||
keywords: string[]
|
||||
score: number
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
export type KbxSeverity = 'info' | 'warning' | 'critical'
|
||||
export type KbxWorkItemStatus = 'open' | 'claimed' | 'resolved' | 'ignored'
|
||||
|
||||
export interface KbxWorkQueueCounter {
|
||||
key: string
|
||||
label: string
|
||||
count: number
|
||||
severity?: KbxSeverity
|
||||
}
|
||||
|
||||
export interface KbxWorkItemAction {
|
||||
id: string
|
||||
label: string
|
||||
kind: 'navigate' | 'claim' | 'resolve' | 'retry' | 'domain'
|
||||
permission?: string
|
||||
permissionMode?: 'hide' | 'disable'
|
||||
danger?: boolean
|
||||
}
|
||||
|
||||
export interface KbxWorkItem {
|
||||
id: string
|
||||
sourceModule: 'OMS' | 'ERP' | 'WMS' | 'COMMON'
|
||||
sourceType: string
|
||||
sourceId: string
|
||||
referenceNo: string
|
||||
sourceScreenId?: string | null
|
||||
code: string
|
||||
title: string
|
||||
detail?: string
|
||||
severity: KbxSeverity
|
||||
status: KbxWorkItemStatus
|
||||
ownerId?: string | null
|
||||
ownerName?: string | null
|
||||
occurredAt: string
|
||||
dueAt?: string | null
|
||||
ageMinutes: number
|
||||
version: number
|
||||
context?: Record<string, unknown>
|
||||
actions?: KbxWorkItemAction[]
|
||||
}
|
||||
|
||||
export interface KbxWorkQueueResult {
|
||||
items: KbxWorkItem[]
|
||||
totalCount: number
|
||||
counters: KbxWorkQueueCounter[]
|
||||
}
|
||||
|
||||
export type KbxReconcileStatus = 'matched' | 'mismatch' | 'pending' | 'resolved'
|
||||
|
||||
export interface KbxReconcileItem {
|
||||
id: string
|
||||
reconcileType: string
|
||||
referenceNo: string
|
||||
sourceLabel: string
|
||||
targetLabel: string
|
||||
expectedValue: string
|
||||
actualValue: string
|
||||
differenceValue?: string | null
|
||||
reasonCode?: string | null
|
||||
reasonText?: string | null
|
||||
status: KbxReconcileStatus
|
||||
occurredAt: string
|
||||
sourceId?: string | null
|
||||
targetId?: string | null
|
||||
version: number
|
||||
}
|
||||
|
||||
export interface KbxReconcileSummary {
|
||||
totalCount: number
|
||||
matchedCount: number
|
||||
mismatchCount: number
|
||||
pendingCount: number
|
||||
resolvedCount: number
|
||||
}
|
||||
|
||||
export interface KbxReconcileResult {
|
||||
items: KbxReconcileItem[]
|
||||
summary: KbxReconcileSummary
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
export interface KbxPerformanceBudget {
|
||||
name: string
|
||||
targetMs: number
|
||||
percentile?: 50 | 95 | 99
|
||||
note: string
|
||||
}
|
||||
|
||||
// Reference acceptance targets. Teams may tighten them after field telemetry,
|
||||
// but should not silently loosen them per screen.
|
||||
export const kbxReferencePerformanceBudgets: KbxPerformanceBudget[] = [
|
||||
{ name: 'keyboard-feedback', targetMs: 100, note: '키 입력/Focus/로컬 선택 피드백' },
|
||||
{ name: 'lookup-search', targetMs: 500, percentile: 95, note: '사내망 기준 Lookup 후보 응답' },
|
||||
{ name: 'filtered-list-search', targetMs: 2000, percentile: 95, note: '일반 업무 조회 첫 결과' },
|
||||
{ name: 'wms-authoritative-scan', targetMs: 500, percentile: 95, note: '현장망 기준 서버 확정 Scan 응답' },
|
||||
{ name: 'foreground-operation', targetMs: 3000, note: '이보다 길면 Operation Center/Job 전환 검토' },
|
||||
]
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface KbxPermissionContext {
|
||||
has(permission: string): boolean
|
||||
hasAny(permissions: readonly string[]): boolean
|
||||
hasAll(permissions: readonly string[]): boolean
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
export type KbxDensity = 'compact' | 'comfortable' | 'touch'
|
||||
|
||||
export interface KbxScreenPreference {
|
||||
screenId: string
|
||||
screenVersion: string
|
||||
density?: KbxDensity
|
||||
grid?: {
|
||||
columnState?: unknown
|
||||
pageSize?: number
|
||||
}
|
||||
searchDefaults?: Record<string, unknown>
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
export interface KbxProblemBase {
|
||||
type: string
|
||||
title: string
|
||||
detail?: string | null
|
||||
correlationId?: string | null
|
||||
}
|
||||
|
||||
export interface KbxValidationError {
|
||||
field?: string | null
|
||||
rowKey?: string | null
|
||||
code: string
|
||||
message: string
|
||||
}
|
||||
|
||||
export interface KbxValidationProblem extends KbxProblemBase {
|
||||
type: 'validation'
|
||||
errors: KbxValidationError[]
|
||||
}
|
||||
|
||||
export interface KbxProblemAction { id: string; label: string }
|
||||
|
||||
export interface KbxBusinessProblem extends KbxProblemBase {
|
||||
type: 'business-rule'
|
||||
code: string
|
||||
actions?: KbxProblemAction[]
|
||||
}
|
||||
|
||||
export interface KbxConflictProblem extends KbxProblemBase {
|
||||
type: 'conflict'
|
||||
code: string
|
||||
currentVersion?: number | null
|
||||
}
|
||||
|
||||
export interface KbxPermissionProblem extends KbxProblemBase {
|
||||
type: 'permission'
|
||||
code: string
|
||||
}
|
||||
|
||||
export interface KbxNotFoundProblem extends KbxProblemBase {
|
||||
type: 'not-found'
|
||||
code: string
|
||||
}
|
||||
|
||||
export interface KbxIntegrationProblem extends KbxProblemBase {
|
||||
type: 'integration'
|
||||
code: string
|
||||
retryable: boolean
|
||||
}
|
||||
|
||||
export interface KbxSystemProblem extends KbxProblemBase {
|
||||
type: 'system'
|
||||
code: string
|
||||
correlationId: string
|
||||
retryable?: boolean
|
||||
}
|
||||
|
||||
export type KbxProblem =
|
||||
| KbxValidationProblem
|
||||
| KbxBusinessProblem
|
||||
| KbxConflictProblem
|
||||
| KbxPermissionProblem
|
||||
| KbxNotFoundProblem
|
||||
| KbxIntegrationProblem
|
||||
| KbxSystemProblem
|
||||
|
||||
const problemTypes = new Set<KbxProblem['type']>([
|
||||
'validation', 'business-rule', 'conflict', 'permission', 'not-found', 'integration', 'system',
|
||||
])
|
||||
|
||||
export function isKbxProblem(value: unknown): value is KbxProblem {
|
||||
if (!value || typeof value !== 'object') return false
|
||||
const problem = value as Record<string, unknown>
|
||||
return typeof problem.type === 'string'
|
||||
&& problemTypes.has(problem.type as KbxProblem['type'])
|
||||
&& typeof problem.title === 'string'
|
||||
}
|
||||
|
||||
export function kbxUnexpectedProblem(correlationId: string, detail?: string, retryable = false): KbxSystemProblem {
|
||||
return {
|
||||
type: 'system',
|
||||
code: 'UNEXPECTED_ERROR',
|
||||
title: '요청을 처리하지 못했습니다.',
|
||||
detail,
|
||||
correlationId,
|
||||
retryable,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function isRetryableKbxProblem(value: unknown): boolean {
|
||||
return isKbxProblem(value)
|
||||
&& ((value.type === 'system' && value.retryable === true)
|
||||
|| (value.type === 'integration' && value.retryable === true))
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
export type KbxExternalProviderPurpose = 'market-data-readonly' | 'disclosure-data-readonly'
|
||||
|
||||
export interface KbxExternalProviderOperationDefinition {
|
||||
id: string
|
||||
method: string
|
||||
path: string
|
||||
response: string
|
||||
trId?: string
|
||||
query?: readonly string[]
|
||||
authOperation?: boolean
|
||||
notes?: string
|
||||
}
|
||||
|
||||
export interface KbxExternalProviderDefinition {
|
||||
id: string
|
||||
title: string
|
||||
ownerModule: 'COMMON' | 'OMS' | 'ERP' | 'WMS'
|
||||
purpose: KbxExternalProviderPurpose
|
||||
mutationAllowed: boolean
|
||||
officialSources: readonly string[]
|
||||
official: Record<string, unknown>
|
||||
kbxPolicy: Record<string, unknown>
|
||||
operations: readonly KbxExternalProviderOperationDefinition[]
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { KbxScreenDefinition } from './screen'
|
||||
|
||||
export interface KbxScreenManifestEntry {
|
||||
id: string
|
||||
version: string
|
||||
module: KbxScreenDefinition['module']
|
||||
type: KbxScreenDefinition['type']
|
||||
templateCode: KbxScreenDefinition['templateCode']
|
||||
title: string
|
||||
route?: string
|
||||
helpKey?: string
|
||||
requiredPermissions: string[]
|
||||
}
|
||||
|
||||
export interface KbxComponentManifestEntry {
|
||||
name: string
|
||||
category: 'primitive' | 'business' | 'template' | 'wms' | 'shell'
|
||||
purpose: string
|
||||
allowedUse?: string[]
|
||||
forbiddenUse?: string[]
|
||||
keyboard?: string[]
|
||||
accessibility?: string[]
|
||||
examples?: string[]
|
||||
owner: 'KBX'
|
||||
version: string
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
export type KbxRuntimeMode = 'normal' | 'degraded' | 'read-only' | 'offline'
|
||||
|
||||
export interface KbxRuntimeNotice {
|
||||
mode: KbxRuntimeMode
|
||||
title: string
|
||||
message?: string
|
||||
since?: string
|
||||
correlationId?: string
|
||||
retryAllowed?: boolean
|
||||
}
|
||||
|
||||
export interface KbxDataFreshness {
|
||||
observedAt: string
|
||||
staleAfterSeconds?: number
|
||||
source?: string
|
||||
}
|
||||
|
||||
export type KbxOperationStatus =
|
||||
| 'queued'
|
||||
| 'running'
|
||||
| 'completed'
|
||||
| 'partially-completed'
|
||||
| 'failed'
|
||||
| 'cancelled'
|
||||
|
||||
export interface KbxOperationRun {
|
||||
id: string
|
||||
type: string
|
||||
title: string
|
||||
sourceScreenId?: string
|
||||
status: KbxOperationStatus
|
||||
requestedAt: string
|
||||
startedAt?: string
|
||||
completedAt?: string
|
||||
processed?: number
|
||||
total?: number
|
||||
succeeded?: number
|
||||
failed?: number
|
||||
correlationId?: string
|
||||
resultMessage?: string
|
||||
}
|
||||
|
||||
export type KbxNotificationSeverity = 'info' | 'success' | 'warning' | 'error'
|
||||
|
||||
export interface KbxUserNotification {
|
||||
id: string
|
||||
severity: KbxNotificationSeverity
|
||||
title: string
|
||||
message?: string
|
||||
createdAt: string
|
||||
readAt?: string
|
||||
screenId?: string
|
||||
entityType?: string
|
||||
entityId?: string
|
||||
action?: {
|
||||
id: string
|
||||
label: string
|
||||
route?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface KbxConflictFieldChange {
|
||||
field: string
|
||||
label: string
|
||||
mine?: unknown
|
||||
latest?: unknown
|
||||
}
|
||||
|
||||
export interface KbxConflictSnapshot {
|
||||
code: string
|
||||
title: string
|
||||
detail?: string
|
||||
entityId?: string
|
||||
requestedVersion?: number
|
||||
currentVersion?: number
|
||||
changes?: KbxConflictFieldChange[]
|
||||
correlationId?: string
|
||||
}
|
||||
|
||||
export interface KbxDiagnosticReference {
|
||||
correlationId: string
|
||||
requestId?: string
|
||||
occurredAt: string
|
||||
screenId?: string
|
||||
screenVersion?: string
|
||||
appVersion?: string
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import type { KbxCommandDefinition } from './command'
|
||||
|
||||
export type KbxScreenType =
|
||||
| 'list'
|
||||
| 'master'
|
||||
| 'transaction'
|
||||
| 'fast-entry'
|
||||
| 'master-detail'
|
||||
| 'queue'
|
||||
| 'reconcile'
|
||||
| 'import'
|
||||
| 'wms-mobile'
|
||||
|
||||
export type KbxTemplateMetricTone = 'default' | 'info' | 'success' | 'warning' | 'danger'
|
||||
|
||||
export type KbxTemplateStateCapability =
|
||||
| 'idle'
|
||||
| 'loading'
|
||||
| 'refreshing'
|
||||
| 'empty'
|
||||
| 'error'
|
||||
| 'permission'
|
||||
| 'dirty'
|
||||
| 'conflict'
|
||||
| 'validation'
|
||||
| 'job'
|
||||
| 'network'
|
||||
|
||||
export interface KbxTemplateMetric {
|
||||
key: string
|
||||
label: string
|
||||
value: string | number
|
||||
tone?: KbxTemplateMetricTone
|
||||
emphasis?: boolean
|
||||
}
|
||||
|
||||
export interface KbxTemplateContext {
|
||||
label?: string
|
||||
hint?: string
|
||||
updatedAt?: string
|
||||
metrics?: KbxTemplateMetric[]
|
||||
}
|
||||
|
||||
|
||||
export interface KbxTemplateManifestEntry {
|
||||
code: 'T01'|'T02'|'T03'|'T04'|'T05'|'T06'|'T07'|'T08'|'T09'
|
||||
type: KbxScreenType
|
||||
component: string
|
||||
purpose: string
|
||||
requiredSurfaces: string[]
|
||||
optionalSurfaces: string[]
|
||||
keyboard: string[]
|
||||
referenceScreens: string[]
|
||||
defaultDensity: 'compact' | 'comfortable' | 'touch'
|
||||
runtimeStates: ('idle'|'loading'|'empty'|'error'|'ready')[]
|
||||
/** State concerns the template must expose or deliberately delegate to a shared KBX component. */
|
||||
stateCapabilities: KbxTemplateStateCapability[]
|
||||
utilitySurfaces: ('help'|'ai'|'suggestion'|'audit')[]
|
||||
accessibility: string[]
|
||||
/** Canonical KBX components expected for a production-grade implementation of this template. */
|
||||
coreComponents: string[]
|
||||
/** Review items that must be resolved before a screen of this type is considered complete. */
|
||||
completionChecks: string[]
|
||||
}
|
||||
|
||||
export type KbxScreenTemplateCode = 'T01'|'T02'|'T03'|'T04'|'T05'|'T06'|'T07'|'T08'|'T09'
|
||||
|
||||
export type KbxRecipePermissionKind = 'none'|'write'|'execute'
|
||||
|
||||
export interface KbxScreenRecipeCommand {
|
||||
id: string
|
||||
label: string
|
||||
group: 'query'|'edit'|'workflow'|'output'|'more'
|
||||
shortcut?: string
|
||||
variant?: 'primary'|'secondary'|'danger'|'ghost'
|
||||
permissionKind: KbxRecipePermissionKind
|
||||
}
|
||||
|
||||
export interface KbxScreenRecipeTestProfile {
|
||||
/** Scenario kinds that must exist in the canonical recipe coverage. */
|
||||
requiredScenarioKinds: ('e2e'|'integration'|'contract')[]
|
||||
/** Behavioral tags that must be covered by the recipe's canonical scenarios. */
|
||||
requiredTags: string[]
|
||||
/** Evidence classes that must be emitted by at least one canonical scenario. */
|
||||
requiredEvidence: string[]
|
||||
/** Stable review/test intents generated for every screen using the recipe. */
|
||||
requiredChecks: string[]
|
||||
}
|
||||
|
||||
export interface KbxScreenRecipeDefinition {
|
||||
code: KbxScreenTemplateCode
|
||||
type: KbxScreenType
|
||||
templateComponent: string
|
||||
defaultCommands: KbxScreenRecipeCommand[]
|
||||
requiredPolicies: string[]
|
||||
recoveryPolicies: string[]
|
||||
securityPolicies: string[]
|
||||
canonicalScenarioIds: string[]
|
||||
scaffoldSurfaces: string[]
|
||||
testProfile: KbxScreenRecipeTestProfile
|
||||
}
|
||||
|
||||
export interface KbxScreenDefinition {
|
||||
id: string
|
||||
version: string
|
||||
module: 'OMS' | 'ERP' | 'WMS' | 'COMMON'
|
||||
type: KbxScreenType
|
||||
/** Explicit template/recipe identity. Type and templateCode must agree. */
|
||||
templateCode: KbxScreenTemplateCode
|
||||
title: string
|
||||
description?: string
|
||||
permissions?: string[]
|
||||
commands?: KbxCommandDefinition[]
|
||||
helpKey?: string
|
||||
telemetry?: { enabled: boolean }
|
||||
}
|
||||
|
||||
export function defineKbxScreen<T extends KbxScreenDefinition>(definition: T): T {
|
||||
return definition
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { KbxLookupDefinition } from './lookup'
|
||||
|
||||
export type KbxSearchFieldType = 'text' | 'date' | 'date-range' | 'select' | 'lookup' | 'checkbox'
|
||||
|
||||
export interface KbxSearchOption {
|
||||
value: string
|
||||
label: string
|
||||
}
|
||||
|
||||
export interface KbxSearchField {
|
||||
key: string
|
||||
label: string
|
||||
type: KbxSearchFieldType
|
||||
primary?: boolean
|
||||
width?: 'sm' | 'md' | 'lg'
|
||||
options?: KbxSearchOption[]
|
||||
lookup?: KbxLookupDefinition
|
||||
range?: { from: string; to: string }
|
||||
placeholder?: string
|
||||
defaultValue?: unknown
|
||||
disabled?: boolean
|
||||
helpText?: string
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
export type KbxStatusSemantic =
|
||||
| 'draft'
|
||||
| 'pending'
|
||||
| 'processing'
|
||||
| 'completed'
|
||||
| 'hold'
|
||||
| 'warning'
|
||||
| 'error'
|
||||
| 'cancelled'
|
||||
| 'disabled'
|
||||
|
||||
export interface KbxStatusDefinition {
|
||||
value: string
|
||||
label: string
|
||||
semantic: KbxStatusSemantic
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
export type KbxSuggestionCategory = 'inconvenience' | 'bug' | 'improvement'
|
||||
|
||||
export interface KbxSuggestionContext {
|
||||
screenId: string
|
||||
screenVersion: string
|
||||
route: string
|
||||
appVersion: string
|
||||
userRole: string
|
||||
activeFilters?: string[]
|
||||
gridLayoutVersion?: string
|
||||
}
|
||||
|
||||
export interface KbxSuggestionRequest {
|
||||
category: KbxSuggestionCategory
|
||||
message: string
|
||||
includeScreenContext: boolean
|
||||
context: KbxSuggestionContext
|
||||
}
|
||||
|
||||
export interface KbxSuggestionResult {
|
||||
suggestionId: string
|
||||
receivedAt: string
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { KbxTelemetryEventName } from './generated/telemetryCatalog'
|
||||
|
||||
export type KbxTelemetryCategory = 'navigation' | 'task' | 'interaction' | 'command' | 'lookup' | 'quality' | 'excel' | 'exception' | 'ai' | 'outcome' | 'experiment'
|
||||
|
||||
export interface KbxUxEvent {
|
||||
eventName: KbxTelemetryEventName
|
||||
screenId?: string
|
||||
screenVersion?: string
|
||||
sessionId: string
|
||||
taskSessionId?: string
|
||||
appVersion?: string
|
||||
experimentId?: string
|
||||
experimentVariant?: string
|
||||
occurredAt: string
|
||||
durationMs?: number
|
||||
count?: number
|
||||
attributes?: Record<string, string>
|
||||
}
|
||||
|
||||
export interface KbxUxEventBatch {
|
||||
events: KbxUxEvent[]
|
||||
}
|
||||
|
||||
export interface KbxUxMetricRow {
|
||||
metricKey: string
|
||||
label: string
|
||||
value: number | null
|
||||
unit: 'ms' | 'percent' | 'count'
|
||||
sampleCount: number
|
||||
p50?: number | null
|
||||
p95?: number | null
|
||||
}
|
||||
|
||||
export interface KbxUxMetricsResponse {
|
||||
from: string
|
||||
to: string
|
||||
screenId?: string | null
|
||||
metrics: KbxUxMetricRow[]
|
||||
}
|
||||
|
||||
export interface KbxUxWorkloadOutcome {
|
||||
workType: string
|
||||
observedCount: number
|
||||
autoProcessedCount: number
|
||||
manualInterventionCount: number
|
||||
reasonCode?: string
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
export type KbxTestScenarioKind = 'e2e' | 'integration' | 'contract'
|
||||
export type KbxTestIsolation = 'database-reset' | 'tenant-reset' | 'ui-only'
|
||||
|
||||
export interface KbxTestScenarioDefinition {
|
||||
id: string
|
||||
title: string
|
||||
screenId: string
|
||||
kind: KbxTestScenarioKind
|
||||
tags: ReadonlyArray<string>
|
||||
fixtureSets: ReadonlyArray<string>
|
||||
requiredPermissions: ReadonlyArray<string>
|
||||
apiOperations: ReadonlyArray<string>
|
||||
isolation: KbxTestIsolation
|
||||
steps: ReadonlyArray<Record<string, unknown>>
|
||||
assertions: ReadonlyArray<string>
|
||||
evidence: ReadonlyArray<string>
|
||||
}
|
||||
|
||||
export interface KbxTestFixtureSetDefinition {
|
||||
id: string
|
||||
description: string
|
||||
refs: ReadonlyArray<string>
|
||||
}
|
||||
|
||||
|
||||
export interface KbxGeneratedScreenTestPlan {
|
||||
screenId: string
|
||||
templateCode: 'T01'|'T02'|'T03'|'T04'|'T05'|'T06'|'T07'|'T08'|'T09'
|
||||
canonicalScenarioIds: ReadonlyArray<string>
|
||||
requiredChecks: ReadonlyArray<string>
|
||||
requiredEvidence: ReadonlyArray<string>
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
export type KbxTransactionMode = 'new' | 'edit' | 'view'
|
||||
|
||||
export interface KbxTransactionContext<THeader, TLine> {
|
||||
header: THeader
|
||||
lines: TLine[]
|
||||
mode: KbxTransactionMode
|
||||
status: string
|
||||
dirty: boolean
|
||||
version?: number
|
||||
}
|
||||
|
||||
|
||||
export type KbxRecordEditability = 'editable' | 'restricted' | 'readonly'
|
||||
|
||||
export interface KbxRecordStatePolicy {
|
||||
status: string
|
||||
editability: KbxRecordEditability
|
||||
editableFields?: string[]
|
||||
message?: string
|
||||
}
|
||||
|
||||
export function resolveKbxRecordStatePolicy(policies: KbxRecordStatePolicy[], status: string): KbxRecordStatePolicy {
|
||||
return policies.find(x => x.status === status) ?? { status, editability: 'readonly', message: '현재 상태에서는 수정할 수 없습니다.' }
|
||||
}
|
||||
|
||||
export function kbxFieldReadonly(policy: KbxRecordStatePolicy, field: string): boolean {
|
||||
if (policy.editability === 'readonly') return true
|
||||
if (policy.editability === 'editable') return false
|
||||
return !(policy.editableFields ?? []).includes(field)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
export type KbxFieldState = 'default' | 'changed' | 'warning' | 'ai-suggested'
|
||||
|
||||
export type KbxAsyncState = 'idle' | 'ready' | 'loading' | 'empty' | 'error'
|
||||
|
||||
export interface KbxAsyncStateDefinition {
|
||||
state: KbxAsyncState
|
||||
title?: string
|
||||
detail?: string
|
||||
actionLabel?: string
|
||||
}
|
||||
|
||||
|
||||
|
||||
export interface KbxSummaryItem {
|
||||
key: string
|
||||
label: string
|
||||
value: string | number
|
||||
emphasis?: boolean
|
||||
}
|
||||
|
||||
export interface KbxQuickFilterItem {
|
||||
key: string
|
||||
label: string
|
||||
count: number
|
||||
active?: boolean
|
||||
tone?: 'default' | 'warning' | 'danger'
|
||||
}
|
||||
|
||||
export type KbxShortcutScope = 'application' | 'page' | 'grid' | 'dialog' | 'editor'
|
||||
|
||||
export interface KbxShortcutDefinition {
|
||||
key: string
|
||||
scope: KbxShortcutScope
|
||||
priority?: number
|
||||
enabled?: () => boolean
|
||||
execute(): void | Promise<void>
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
export type KbxBarcodeSource = 'keyboard-wedge' | 'camera' | 'manual'
|
||||
|
||||
export interface KbxBarcodeEvent {
|
||||
rawValue: string
|
||||
normalizedValue: string
|
||||
source: KbxBarcodeSource
|
||||
occurredAt: number
|
||||
}
|
||||
|
||||
export type KbxWmsPickingStage =
|
||||
| 'ready'
|
||||
| 'await-location'
|
||||
| 'await-item'
|
||||
| 'processing'
|
||||
| 'completed'
|
||||
| 'blocked'
|
||||
|
||||
export interface KbxWmsCurrentLine {
|
||||
lineId: string
|
||||
lineNo: number
|
||||
locationCode: string
|
||||
itemId: string
|
||||
itemCode: string
|
||||
itemName: string
|
||||
itemOption?: string | null
|
||||
barcode: string
|
||||
requiredQty: number
|
||||
pickedQty: number
|
||||
remainingQty: number
|
||||
}
|
||||
|
||||
export interface KbxWmsPickingTask {
|
||||
taskId: string
|
||||
taskNo: string
|
||||
stage: KbxWmsPickingStage
|
||||
status: string
|
||||
completedLines: number
|
||||
totalLines: number
|
||||
completedQty: number
|
||||
totalQty: number
|
||||
version: number
|
||||
currentLine?: KbxWmsCurrentLine | null
|
||||
message?: string | null
|
||||
}
|
||||
|
||||
export interface KbxWmsScanCommand {
|
||||
taskId: string
|
||||
barcode: string
|
||||
source: KbxBarcodeSource
|
||||
idempotencyKey: string
|
||||
expectedVersion: number
|
||||
occurredAt: string
|
||||
}
|
||||
|
||||
export interface KbxWmsScanResult {
|
||||
accepted: boolean
|
||||
duplicate: boolean
|
||||
task: KbxWmsPickingTask
|
||||
feedback: 'success' | 'warning' | 'error' | 'neutral'
|
||||
message: string
|
||||
}
|
||||
|
||||
export type KbxWmsExceptionType =
|
||||
| 'no-stock'
|
||||
| 'short-quantity'
|
||||
| 'wrong-location'
|
||||
| 'damaged-item'
|
||||
| 'barcode-issue'
|
||||
| 'other'
|
||||
|
||||
export interface KbxWmsExceptionCommand {
|
||||
taskId: string
|
||||
lineId?: string | null
|
||||
type: KbxWmsExceptionType
|
||||
memo?: string | null
|
||||
idempotencyKey: string
|
||||
expectedVersion: number
|
||||
}
|
||||
|
||||
export interface KbxWmsNetworkState {
|
||||
online: boolean
|
||||
pendingCommands: number
|
||||
syncing: boolean
|
||||
}
|
||||
|
||||
export interface KbxWmsSetQuantityCommand {
|
||||
taskId: string
|
||||
lineId: string
|
||||
pickedQty: number
|
||||
idempotencyKey: string
|
||||
expectedVersion: number
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
import type { KbxStatusSemantic } from './status'
|
||||
|
||||
export interface KbxWorkflowStateDefinition {
|
||||
value: string
|
||||
label: string
|
||||
semantic: KbxStatusSemantic
|
||||
terminal?: boolean
|
||||
}
|
||||
|
||||
export interface KbxWorkflowTransitionDefinition {
|
||||
id: string
|
||||
from: string[]
|
||||
to: string
|
||||
label: string
|
||||
permission?: string
|
||||
confirm?: boolean
|
||||
reasonRequired?: boolean
|
||||
}
|
||||
|
||||
export interface KbxWorkflowDefinition {
|
||||
id: string
|
||||
version: string
|
||||
states: KbxWorkflowStateDefinition[]
|
||||
transitions: KbxWorkflowTransitionDefinition[]
|
||||
}
|
||||
|
||||
export function allowedKbxTransitions(workflow: KbxWorkflowDefinition, current: string) {
|
||||
return workflow.transitions.filter(x => x.from.includes(current))
|
||||
}
|
||||
Reference in New Issue
Block a user