@praxisui/files-upload 8.0.0-beta.1 → 8.0.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -271,6 +271,32 @@ const cfg: FilesUploadConfig = {
271
271
  - `maxFilesPerBulkValidator`
272
272
  - `maxBulkSizeValidator`
273
273
 
274
+ ## Agentic Authoring Contract
275
+
276
+ `@praxisui/files-upload` publishes an executable `ComponentAuthoringManifest` through
277
+ `PRAXIS_FILES_UPLOAD_AUTHORING_MANIFEST`.
278
+
279
+ The contract exposes typed operation families for:
280
+
281
+ - accepted types: `accept.types.set`
282
+ - single-file and batch limits: `limit.fileSize.set`, `limit.fileCount.set`
283
+ - backend upload surfaces: `endpoint.presign.set`, `endpoint.upload.set`
284
+ - upload policy: `security.policy.set`
285
+ - error message overrides: `message.error.set`
286
+ - display mode and UI flags: `display.mode.set`
287
+
288
+ Endpoint authoring intentionally changes only the canonical `baseUrl` runtime input
289
+ and the upload `strategy`. The direct, bulk and presign paths remain fixed as
290
+ `baseUrl/upload`, `baseUrl/bulk` and `baseUrl/upload/presign?filename=...` so hosts
291
+ do not create parallel endpoint semantics outside `FilesApiClient`.
292
+
293
+ Every manifest operation declares its own editable target resolver, ambiguity policy,
294
+ preconditions, validators, affected paths, effects and typed submission impact. Upload
295
+ limits and accepted types are marked as submission-affecting; endpoint and security
296
+ policy edits are marked as remote-binding changes and require confirmation; error
297
+ messages are config-only; display changes are visual-only. These categories are the
298
+ same metadata projected into `praxis-component-registry-ingestion.json`.
299
+
274
300
  ## Error handling
275
301
 
276
302
  `ErrorMapperService` translates backend error codes from `errors[0]` into user-facing messages and exposes rate limit information.
@@ -6358,6 +6358,12 @@ const PRAXIS_FILES_UPLOAD_COMPONENT_METADATA = {
6358
6358
  label: 'Arquivos pendentes',
6359
6359
  description: 'Disparado quando o estado de selecao pendente muda.',
6360
6360
  },
6361
+ {
6362
+ name: 'readinessChange',
6363
+ type: 'FilesUploadReadinessEvent',
6364
+ label: 'Prontidao',
6365
+ description: 'Disparado quando o componente alterna entre configuracao local, servidor ou fallback.',
6366
+ },
6361
6367
  {
6362
6368
  name: 'proximityChange',
6363
6369
  type: 'boolean',
@@ -6559,10 +6565,335 @@ const FILES_UPLOAD_AI_CAPABILITIES = {
6559
6565
  ],
6560
6566
  };
6561
6567
 
6568
+ const PRAXIS_FILES_UPLOAD_AUTHORING_MANIFEST = {
6569
+ schemaVersion: '1.0.0',
6570
+ componentId: 'praxis-files-upload',
6571
+ ownerPackage: '@praxisui/files-upload',
6572
+ configSchemaId: 'FilesUploadConfig',
6573
+ manifestVersion: '1.0.0',
6574
+ runtimeInputs: [
6575
+ { name: 'config', type: 'FilesUploadConfig', description: 'Upload strategy, UI, limits, backend options, bulk execution, quota/rate feedback, headers and messages.' },
6576
+ { name: 'filesUploadId', type: 'string', description: 'Stable upload id used for config persistence and telemetry correlation.' },
6577
+ { name: 'componentInstanceId', type: 'string', description: 'Optional instance discriminator when the same upload id appears more than once.' },
6578
+ { name: 'baseUrl', type: 'string', description: 'Canonical files API base URL. Direct upload uses baseUrl/upload, bulk uses baseUrl/bulk and presign uses baseUrl/upload/presign.' },
6579
+ { name: 'displayMode', type: "'full' | 'compact'", allowedValues: ['full', 'compact'], description: 'Runtime display mode input.' },
6580
+ { name: 'context', type: 'Record<string, unknown>', description: 'Host context available to metadata and event consumers.' },
6581
+ { name: 'enableCustomization', type: 'boolean', description: 'Enables the Settings Panel configuration editor.' },
6582
+ ],
6583
+ editableTargets: [
6584
+ { kind: 'acceptedTypes', resolver: 'files-accept-list', description: 'Allowed file extensions and MIME types projected to ui.accept, options.allowedExtensions and options.acceptMimeTypes.' },
6585
+ { kind: 'sizeLimit', resolver: 'max-file-size-policy', description: 'Maximum single-file size in limits.maxFileSizeBytes and backend-facing options.maxUploadSizeMb.' },
6586
+ { kind: 'fileCountLimit', resolver: 'max-files-per-bulk-policy', description: 'Maximum number of files accepted in a bulk selection.' },
6587
+ { kind: 'presignEndpoint', resolver: 'files-api-base-url-presign-contract', description: 'Presign operation endpoint derived from baseUrl + /upload/presign; arbitrary per-operation URLs are not accepted.' },
6588
+ { kind: 'uploadEndpoint', resolver: 'files-api-base-url-upload-contract', description: 'Direct and bulk upload endpoints derived from baseUrl + /upload and /bulk.' },
6589
+ { kind: 'securityPolicy', resolver: 'upload-security-policy', description: 'Strict validation, virus scanning, conflict policy, target directory, quotas, rate limit and contextual headers.' },
6590
+ { kind: 'errorMessages', resolver: 'upload-error-code-message', description: 'Host-provided message overrides under messages.errors keyed by backend error code.' },
6591
+ { kind: 'display', resolver: 'files-upload-display-mode-and-ui', description: 'Runtime displayMode plus non-backend visual UI flags.' },
6592
+ ],
6593
+ operations: [
6594
+ {
6595
+ operationId: 'accept.types.set',
6596
+ title: 'Set accepted file types',
6597
+ scope: 'global',
6598
+ targetKind: 'acceptedTypes',
6599
+ target: { kind: 'acceptedTypes', resolver: 'files-accept-list', ambiguityPolicy: 'fail', required: false },
6600
+ inputSchema: {
6601
+ type: 'object',
6602
+ required: ['accept'],
6603
+ properties: {
6604
+ accept: { type: 'array', items: { type: 'string' } },
6605
+ allowedExtensions: { type: 'array', items: { type: 'string' } },
6606
+ acceptMimeTypes: { type: 'array', items: { type: 'string' } },
6607
+ },
6608
+ },
6609
+ effects: [
6610
+ { kind: 'set-value', path: 'ui.accept' },
6611
+ { kind: 'set-value', path: 'options.allowedExtensions' },
6612
+ { kind: 'set-value', path: 'options.acceptMimeTypes' },
6613
+ ],
6614
+ destructive: false,
6615
+ requiresConfirmation: false,
6616
+ validators: ['file-type-list-explicit', 'file-type-entry-valid', 'backend-accept-options-consistent', 'editor-runtime-round-trip'],
6617
+ affectedPaths: ['ui.accept', 'options.allowedExtensions', 'options.acceptMimeTypes'],
6618
+ submissionImpact: 'affects-submission',
6619
+ preconditions: ['config-initialized'],
6620
+ },
6621
+ {
6622
+ operationId: 'limit.fileSize.set',
6623
+ title: 'Set max file size',
6624
+ scope: 'global',
6625
+ targetKind: 'sizeLimit',
6626
+ target: { kind: 'sizeLimit', resolver: 'max-file-size-policy', ambiguityPolicy: 'fail', required: false },
6627
+ inputSchema: {
6628
+ type: 'object',
6629
+ required: ['maxFileSizeBytes'],
6630
+ properties: {
6631
+ maxFileSizeBytes: { type: 'number' },
6632
+ maxUploadSizeMb: { type: 'number' },
6633
+ },
6634
+ },
6635
+ effects: [
6636
+ { kind: 'set-value', path: 'limits.maxFileSizeBytes' },
6637
+ { kind: 'set-value', path: 'options.maxUploadSizeMb' },
6638
+ ],
6639
+ destructive: false,
6640
+ requiresConfirmation: false,
6641
+ validators: ['size-limit-numeric', 'size-limit-within-platform-policy', 'size-limit-client-backend-consistent', 'editor-runtime-round-trip'],
6642
+ affectedPaths: ['limits.maxFileSizeBytes', 'options.maxUploadSizeMb'],
6643
+ submissionImpact: 'affects-submission',
6644
+ preconditions: ['config-initialized'],
6645
+ },
6646
+ {
6647
+ operationId: 'limit.fileCount.set',
6648
+ title: 'Set max file count',
6649
+ scope: 'global',
6650
+ targetKind: 'fileCountLimit',
6651
+ target: { kind: 'fileCountLimit', resolver: 'max-files-per-bulk-policy', ambiguityPolicy: 'fail', required: false },
6652
+ inputSchema: {
6653
+ type: 'object',
6654
+ required: ['maxFilesPerBulk'],
6655
+ properties: {
6656
+ maxFilesPerBulk: { type: 'number' },
6657
+ maxBulkSizeBytes: { type: 'number' },
6658
+ },
6659
+ },
6660
+ effects: [
6661
+ { kind: 'set-value', path: 'limits.maxFilesPerBulk' },
6662
+ { kind: 'set-value', path: 'limits.maxBulkSizeBytes' },
6663
+ ],
6664
+ destructive: false,
6665
+ requiresConfirmation: false,
6666
+ validators: ['file-count-limit-numeric', 'bulk-size-limit-numeric', 'bulk-limit-within-platform-policy', 'editor-runtime-round-trip'],
6667
+ affectedPaths: ['limits.maxFilesPerBulk', 'limits.maxBulkSizeBytes'],
6668
+ submissionImpact: 'affects-submission',
6669
+ preconditions: ['config-initialized'],
6670
+ },
6671
+ {
6672
+ operationId: 'endpoint.presign.set',
6673
+ title: 'Set presign endpoint',
6674
+ scope: 'global',
6675
+ targetKind: 'presignEndpoint',
6676
+ target: { kind: 'presignEndpoint', resolver: 'files-api-base-url-presign-contract', ambiguityPolicy: 'fail', required: false },
6677
+ inputSchema: {
6678
+ type: 'object',
6679
+ required: ['baseUrl'],
6680
+ properties: {
6681
+ baseUrl: { type: 'string' },
6682
+ strategy: { enum: ['direct', 'presign', 'auto'] },
6683
+ allowCrossOriginPresignedTarget: { type: 'boolean' },
6684
+ },
6685
+ },
6686
+ effects: [{
6687
+ kind: 'compile-domain-patch',
6688
+ handler: 'files-upload-presign-base-url',
6689
+ handlerContract: {
6690
+ reads: ['baseUrl', 'strategy'],
6691
+ writes: ['baseUrl', 'strategy'],
6692
+ identityKeys: ['baseUrl'],
6693
+ inputSchema: {
6694
+ type: 'object',
6695
+ required: ['baseUrl'],
6696
+ properties: {
6697
+ baseUrl: { type: 'string' },
6698
+ strategy: { enum: ['direct', 'presign', 'auto'] },
6699
+ allowCrossOriginPresignedTarget: { type: 'boolean' },
6700
+ },
6701
+ },
6702
+ failureModes: ['unsafe-url', 'non-praxis-backend-surface', 'presign-path-override', 'cross-origin-presigned-fields-leak'],
6703
+ description: 'Validates the files API base URL and preserves the canonical POST baseUrl/upload/presign?filename=... contract; arbitrary presign URLs are rejected.',
6704
+ },
6705
+ }],
6706
+ destructive: true,
6707
+ requiresConfirmation: true,
6708
+ validators: ['endpoint-url-safe', 'endpoint-uses-praxis-backend-surface', 'presign-endpoint-fixed-contract', 'presign-cross-origin-fields-safe', 'security-change-confirmed'],
6709
+ affectedPaths: ['baseUrl', 'strategy'],
6710
+ submissionImpact: 'affects-remote-binding',
6711
+ preconditions: ['config-initialized', 'confirmation-collected'],
6712
+ },
6713
+ {
6714
+ operationId: 'endpoint.upload.set',
6715
+ title: 'Set upload endpoint',
6716
+ scope: 'global',
6717
+ targetKind: 'uploadEndpoint',
6718
+ target: { kind: 'uploadEndpoint', resolver: 'files-api-base-url-upload-contract', ambiguityPolicy: 'fail', required: false },
6719
+ inputSchema: {
6720
+ type: 'object',
6721
+ required: ['baseUrl'],
6722
+ properties: {
6723
+ baseUrl: { type: 'string' },
6724
+ strategy: { enum: ['direct', 'presign', 'auto'] },
6725
+ allowCrossOriginPresignedTarget: { type: 'boolean' },
6726
+ },
6727
+ },
6728
+ effects: [{
6729
+ kind: 'compile-domain-patch',
6730
+ handler: 'files-upload-direct-base-url',
6731
+ handlerContract: {
6732
+ reads: ['baseUrl', 'strategy'],
6733
+ writes: ['baseUrl', 'strategy'],
6734
+ identityKeys: ['baseUrl'],
6735
+ inputSchema: {
6736
+ type: 'object',
6737
+ required: ['baseUrl'],
6738
+ properties: {
6739
+ baseUrl: { type: 'string' },
6740
+ strategy: { enum: ['direct', 'presign', 'auto'] },
6741
+ allowCrossOriginPresignedTarget: { type: 'boolean' },
6742
+ },
6743
+ },
6744
+ failureModes: ['unsafe-url', 'non-praxis-backend-surface', 'upload-path-override', 'bulk-path-override'],
6745
+ description: 'Validates the files API base URL and preserves the canonical POST baseUrl/upload and POST baseUrl/bulk contracts.',
6746
+ },
6747
+ }],
6748
+ destructive: true,
6749
+ requiresConfirmation: true,
6750
+ validators: ['endpoint-url-safe', 'endpoint-uses-praxis-backend-surface', 'upload-endpoint-fixed-contract', 'bulk-endpoint-fixed-contract', 'security-change-confirmed'],
6751
+ affectedPaths: ['baseUrl', 'strategy'],
6752
+ submissionImpact: 'affects-remote-binding',
6753
+ preconditions: ['config-initialized', 'confirmation-collected'],
6754
+ },
6755
+ {
6756
+ operationId: 'security.policy.set',
6757
+ title: 'Set upload security policy',
6758
+ scope: 'global',
6759
+ targetKind: 'securityPolicy',
6760
+ target: { kind: 'securityPolicy', resolver: 'upload-security-policy', ambiguityPolicy: 'fail', required: false },
6761
+ inputSchema: {
6762
+ type: 'object',
6763
+ properties: {
6764
+ strictValidation: { type: 'boolean' },
6765
+ enableVirusScanning: { type: 'boolean' },
6766
+ defaultConflictPolicy: { enum: ['ERROR', 'SKIP', 'OVERWRITE', 'MAKE_UNIQUE', 'RENAME'] },
6767
+ targetDirectory: { type: 'string' },
6768
+ showQuotaWarnings: { type: 'boolean' },
6769
+ blockOnExceed: { type: 'boolean' },
6770
+ autoRetryOn429: { type: 'boolean' },
6771
+ showBannerOn429: { type: 'boolean' },
6772
+ maxAutoRetry: { type: 'number' },
6773
+ baseBackoffMs: { type: 'number' },
6774
+ tenantHeader: { type: 'string' },
6775
+ userHeader: { type: 'string' },
6776
+ },
6777
+ },
6778
+ effects: [
6779
+ { kind: 'merge-object', path: 'options' },
6780
+ { kind: 'merge-object', path: 'quotas' },
6781
+ { kind: 'merge-object', path: 'rateLimit' },
6782
+ { kind: 'merge-object', path: 'headers' },
6783
+ ],
6784
+ destructive: true,
6785
+ requiresConfirmation: true,
6786
+ validators: ['security-change-confirmed', 'security-policy-compatible', 'target-directory-safe', 'conflict-policy-valid', 'quota-rate-policy-valid', 'header-names-safe', 'editor-runtime-round-trip'],
6787
+ affectedPaths: ['options.strictValidation', 'options.enableVirusScanning', 'options.defaultConflictPolicy', 'options.targetDirectory', 'quotas', 'rateLimit', 'headers'],
6788
+ submissionImpact: 'config-only',
6789
+ preconditions: ['config-initialized', 'confirmation-collected'],
6790
+ },
6791
+ {
6792
+ operationId: 'message.error.set',
6793
+ title: 'Set error message override',
6794
+ scope: 'global',
6795
+ targetKind: 'errorMessages',
6796
+ target: { kind: 'errorMessages', resolver: 'upload-error-code-message', ambiguityPolicy: 'fail', required: false },
6797
+ inputSchema: {
6798
+ type: 'object',
6799
+ required: ['code', 'message'],
6800
+ properties: {
6801
+ code: { type: 'string' },
6802
+ message: { type: 'string' },
6803
+ },
6804
+ },
6805
+ effects: [{ kind: 'merge-object', path: 'messages.errors' }],
6806
+ destructive: false,
6807
+ requiresConfirmation: false,
6808
+ validators: ['error-code-known', 'error-message-i18n-compatible', 'message-not-empty', 'editor-runtime-round-trip'],
6809
+ affectedPaths: ['messages.errors'],
6810
+ submissionImpact: 'config-only',
6811
+ preconditions: ['config-initialized'],
6812
+ },
6813
+ {
6814
+ operationId: 'display.mode.set',
6815
+ title: 'Set display mode',
6816
+ scope: 'global',
6817
+ targetKind: 'display',
6818
+ target: { kind: 'display', resolver: 'files-upload-display-mode-and-ui', ambiguityPolicy: 'fail', required: false },
6819
+ inputSchema: {
6820
+ type: 'object',
6821
+ properties: {
6822
+ displayMode: { enum: ['full', 'compact'] },
6823
+ dense: { type: 'boolean' },
6824
+ showDropzone: { type: 'boolean' },
6825
+ showProgress: { type: 'boolean' },
6826
+ manualUpload: { type: 'boolean' },
6827
+ showMetadataForm: { type: 'boolean' },
6828
+ showConflictPolicySelector: { type: 'boolean' },
6829
+ },
6830
+ },
6831
+ effects: [
6832
+ { kind: 'set-value', path: 'displayMode' },
6833
+ { kind: 'merge-object', path: 'ui' },
6834
+ ],
6835
+ destructive: false,
6836
+ requiresConfirmation: false,
6837
+ validators: ['display-mode-valid', 'display-ui-compatible', 'editor-runtime-round-trip'],
6838
+ affectedPaths: ['displayMode', 'ui.dense', 'ui.showDropzone', 'ui.showProgress', 'ui.manualUpload', 'ui.showMetadataForm', 'ui.showConflictPolicySelector'],
6839
+ submissionImpact: 'visual-only',
6840
+ preconditions: ['config-initialized'],
6841
+ },
6842
+ ],
6843
+ validators: [
6844
+ { validatorId: 'file-type-list-explicit', level: 'error', code: 'PFU001', description: 'Accepted type edits must provide a non-empty explicit list and may not rely on wildcard-only policy.' },
6845
+ { validatorId: 'file-type-entry-valid', level: 'error', code: 'PFU002', description: 'Each accepted type must be a valid extension, exact MIME type or controlled subtype wildcard.' },
6846
+ { validatorId: 'backend-accept-options-consistent', level: 'error', code: 'PFU003', description: 'ui.accept hints must remain consistent with options.allowedExtensions and options.acceptMimeTypes when backend validation is configured.' },
6847
+ { validatorId: 'size-limit-numeric', level: 'error', code: 'PFU004', description: 'Single file size limits must be positive numeric byte and MB values.' },
6848
+ { validatorId: 'size-limit-within-platform-policy', level: 'error', code: 'PFU005', description: 'Single file size limits must not exceed the platform upload policy for the selected backend surface.' },
6849
+ { validatorId: 'size-limit-client-backend-consistent', level: 'error', code: 'PFU006', description: 'limits.maxFileSizeBytes and options.maxUploadSizeMb must describe the same effective maximum when both are present.' },
6850
+ { validatorId: 'file-count-limit-numeric', level: 'error', code: 'PFU007', description: 'Bulk file count limits must be positive integers.' },
6851
+ { validatorId: 'bulk-size-limit-numeric', level: 'error', code: 'PFU008', description: 'Bulk size limits must be positive numeric byte values when provided.' },
6852
+ { validatorId: 'bulk-limit-within-platform-policy', level: 'error', code: 'PFU009', description: 'Bulk count and aggregate size limits must not exceed backend batch policy.' },
6853
+ { validatorId: 'endpoint-url-safe', level: 'error', code: 'PFU010', description: 'Endpoint edits must use a safe absolute or approved relative baseUrl and reject javascript:, data:, credentials-in-URL and path traversal.' },
6854
+ { validatorId: 'endpoint-uses-praxis-backend-surface', level: 'error', code: 'PFU011', description: 'Endpoint edits must resolve to the approved Praxis files backend surface for the host environment.' },
6855
+ { validatorId: 'presign-endpoint-fixed-contract', level: 'error', code: 'PFU012', description: 'Presign authoring may change baseUrl but must preserve POST baseUrl/upload/presign?filename=... as the runtime contract.' },
6856
+ { validatorId: 'upload-endpoint-fixed-contract', level: 'error', code: 'PFU013', description: 'Direct upload authoring may change baseUrl but must preserve POST baseUrl/upload as the runtime contract.' },
6857
+ { validatorId: 'bulk-endpoint-fixed-contract', level: 'error', code: 'PFU014', description: 'Bulk upload authoring may change baseUrl but must preserve POST baseUrl/bulk as the runtime contract.' },
6858
+ { validatorId: 'presign-cross-origin-fields-safe', level: 'error', code: 'PFU015', description: 'Cross-origin presigned upload targets must not receive Praxis metadata/options fields unless explicitly approved by the presign response contract.' },
6859
+ { validatorId: 'security-change-confirmed', level: 'error', code: 'PFU016', description: 'Endpoint and security policy edits require explicit confirmation before patch compilation.' },
6860
+ { validatorId: 'security-policy-compatible', level: 'error', code: 'PFU017', description: 'Strict validation, virus scanning, conflict policy, target directory, quota and rate-limit settings must be compatible with backend effective config.' },
6861
+ { validatorId: 'target-directory-safe', level: 'error', code: 'PFU018', description: 'Target directory values must be normalized backend paths and must reject traversal or absolute filesystem paths.' },
6862
+ { validatorId: 'conflict-policy-valid', level: 'error', code: 'PFU019', description: 'Default conflict policy must be one of ERROR, SKIP, OVERWRITE, MAKE_UNIQUE or RENAME.' },
6863
+ { validatorId: 'quota-rate-policy-valid', level: 'error', code: 'PFU020', description: 'Quota and rate-limit UX settings must use non-negative retry counts/backoffs and cannot silently bypass backend enforcement.' },
6864
+ { validatorId: 'header-names-safe', level: 'warning', code: 'PFU021', description: 'Contextual header names must be explicit HTTP token names and must not override authorization, cookie or content-type headers.' },
6865
+ { validatorId: 'error-code-known', level: 'warning', code: 'PFU022', description: 'Error message overrides should target known backend error catalog codes or documented host-specific extensions.' },
6866
+ { validatorId: 'error-message-i18n-compatible', level: 'warning', code: 'PFU023', description: 'User-facing error messages must remain compatible with the host i18n/editor flow and not expose raw technical exception text.' },
6867
+ { validatorId: 'message-not-empty', level: 'error', code: 'PFU024', description: 'Error message overrides must be non-empty user-facing text.' },
6868
+ { validatorId: 'display-mode-valid', level: 'error', code: 'PFU025', description: 'Display mode must be full or compact.' },
6869
+ { validatorId: 'display-ui-compatible', level: 'warning', code: 'PFU026', description: 'Display changes must keep progress, manual upload and metadata form affordances reachable for the selected mode.' },
6870
+ { validatorId: 'editor-runtime-round-trip', level: 'error', code: 'PFU027', description: 'Settings Panel editor, AI adapter snapshot and runtime inputs must round-trip config, baseUrl and displayMode without changing upload behavior.' },
6871
+ ],
6872
+ roundTripRequirements: [
6873
+ 'Accepted type authoring must keep UI hints and backend-facing validation options aligned; ui.accept alone is not the canonical server policy.',
6874
+ 'Endpoint authoring changes only the canonical files API baseUrl and strategy; direct, bulk and presign paths remain fixed by FilesApiClient.',
6875
+ 'Security-affecting edits require confirmation and must round-trip through Settings Panel persistence without weakening strict validation, virus scanning, quota or rate-limit policy by omission.',
6876
+ 'Error message overrides remain keyed by backend error catalog code and must stay user-facing/i18n-compatible.',
6877
+ 'Display authoring may change displayMode and UI flags, but must not mutate backend options or upload submission payload.',
6878
+ ],
6879
+ examples: [
6880
+ { id: 'accept-pdf-images', request: 'Accept only PDF and image uploads.', operationId: 'accept.types.set', params: { accept: ['application/pdf', 'image/*'], allowedExtensions: ['pdf', 'png', 'jpg', 'jpeg'], acceptMimeTypes: ['application/pdf', 'image/png', 'image/jpeg'] }, isPositive: true },
6881
+ { id: 'max-five-mb', request: 'Limit each file to 5 MB.', operationId: 'limit.fileSize.set', params: { maxFileSizeBytes: 5242880, maxUploadSizeMb: 5 }, isPositive: true },
6882
+ { id: 'max-three-files', request: 'Allow at most three files per upload batch.', operationId: 'limit.fileCount.set', params: { maxFilesPerBulk: 3 }, isPositive: true },
6883
+ { id: 'set-presign-base-url', request: 'Use the official files API for presigned uploads.', operationId: 'endpoint.presign.set', params: { baseUrl: 'https://api.praxis.example/files', strategy: 'presign' }, isPositive: true },
6884
+ { id: 'set-direct-base-url', request: 'Use the official files API for direct uploads.', operationId: 'endpoint.upload.set', params: { baseUrl: 'https://api.praxis.example/files', strategy: 'direct' }, isPositive: true },
6885
+ { id: 'reject-unsafe-endpoint', request: 'Set upload endpoint to javascript:alert(1).', operationId: 'endpoint.upload.set', params: { baseUrl: 'javascript:alert(1)', strategy: 'direct' }, isPositive: false },
6886
+ { id: 'tighten-security-policy', request: 'Enable strict validation and virus scanning for uploads.', operationId: 'security.policy.set', params: { strictValidation: true, enableVirusScanning: true, defaultConflictPolicy: 'ERROR' }, isPositive: true },
6887
+ { id: 'reject-unconfirmed-security-policy', request: 'Disable strict validation without confirmation.', operationId: 'security.policy.set', params: { strictValidation: false, enableVirusScanning: false }, isPositive: false },
6888
+ { id: 'quota-message', request: 'Show a friendly message when quota is exceeded.', operationId: 'message.error.set', params: { code: 'QUOTA_EXCEEDED', message: 'Upload quota reached for this period.' }, isPositive: true },
6889
+ { id: 'compact-display', request: 'Use compact upload display and keep progress visible.', operationId: 'display.mode.set', params: { displayMode: 'compact', dense: true, showProgress: true }, isPositive: true },
6890
+ ],
6891
+ };
6892
+
6562
6893
  // Export all public API from subdirectories
6563
6894
 
6564
6895
  /**
6565
6896
  * Generated bundle index. Do not edit.
6566
6897
  */
6567
6898
 
6568
- export { BulkUploadResultStatus, ErrorCode, ErrorMapperService, FILES_UPLOAD_AI_CAPABILITIES, FILES_UPLOAD_EN_US, FILES_UPLOAD_ERROR_MESSAGES, FILES_UPLOAD_PT_BR, FILES_UPLOAD_TEXTS, FilesApiClient, PRAXIS_FILES_UPLOAD_COMPONENT_METADATA, PdxFilesUploadFieldComponent, PraxisFilesUpload, PraxisFilesUploadConfigEditor, PresignedUploaderService, ScanStatus, TRANSLATE_LIKE, acceptValidator, createPraxisFilesUploadI18nConfig, getPrimaryErrorItem, isErrorEnvelope, maxBulkSizeValidator, maxFileSizeValidator, maxFilesPerBulkValidator, providePraxisFilesUploadI18n, providePraxisFilesUploadMetadata, resolvePraxisFilesUploadText };
6899
+ export { BulkUploadResultStatus, ErrorCode, ErrorMapperService, FILES_UPLOAD_AI_CAPABILITIES, FILES_UPLOAD_EN_US, FILES_UPLOAD_ERROR_MESSAGES, FILES_UPLOAD_PT_BR, FILES_UPLOAD_TEXTS, FilesApiClient, PRAXIS_FILES_UPLOAD_AUTHORING_MANIFEST, PRAXIS_FILES_UPLOAD_COMPONENT_METADATA, PdxFilesUploadFieldComponent, PraxisFilesUpload, PraxisFilesUploadConfigEditor, PresignedUploaderService, ScanStatus, TRANSLATE_LIKE, acceptValidator, createPraxisFilesUploadI18nConfig, getPrimaryErrorItem, isErrorEnvelope, maxBulkSizeValidator, maxFileSizeValidator, maxFilesPerBulkValidator, providePraxisFilesUploadI18n, providePraxisFilesUploadMetadata, resolvePraxisFilesUploadText };
package/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, OnDestroy, NgZone, OnInit, OnChanges, AfterViewInit, EventEmitter, ViewContainerRef, ChangeDetectorRef, DestroyRef, Provider } from '@angular/core';
3
3
  import { FormControl, ValidatorFn, FormGroup, FormBuilder } from '@angular/forms';
4
- import { PraxisI18nDictionary, PraxisI18nConfig, PraxisI18nService, AsyncConfigStorage, ComponentDocMeta, AiCapabilityCategory, AiValueKind, AiCapability, AiCapabilityCatalog } from '@praxisui/core';
4
+ import { PraxisI18nDictionary, PraxisI18nConfig, PraxisI18nService, AsyncConfigStorage, ComponentDocMeta, AiCapabilityCategory, AiValueKind, AiCapability, AiCapabilityCatalog, ComponentAuthoringManifest } from '@praxisui/core';
5
5
  import { SettingsPanelService, SettingsValueProvider } from '@praxisui/settings-panel';
6
6
  import { HttpClient, HttpEvent, HttpHeaders } from '@angular/common/http';
7
7
  import { Observable, BehaviorSubject } from 'rxjs';
@@ -1465,5 +1465,7 @@ interface CapabilityCatalog extends AiCapabilityCatalog {
1465
1465
  }
1466
1466
  declare const FILES_UPLOAD_AI_CAPABILITIES: CapabilityCatalog;
1467
1467
 
1468
- export { BulkUploadResultStatus, ErrorCode, ErrorMapperService, FILES_UPLOAD_AI_CAPABILITIES, FILES_UPLOAD_EN_US, FILES_UPLOAD_ERROR_MESSAGES, FILES_UPLOAD_PT_BR, FILES_UPLOAD_TEXTS, FilesApiClient, PRAXIS_FILES_UPLOAD_COMPONENT_METADATA, PdxFilesUploadFieldComponent, PraxisFilesUpload, PraxisFilesUploadConfigEditor, PresignedUploaderService, ScanStatus, TRANSLATE_LIKE, acceptValidator, createPraxisFilesUploadI18nConfig, getPrimaryErrorItem, isErrorEnvelope, maxBulkSizeValidator, maxFileSizeValidator, maxFilesPerBulkValidator, providePraxisFilesUploadI18n, providePraxisFilesUploadMetadata, resolvePraxisFilesUploadText };
1468
+ declare const PRAXIS_FILES_UPLOAD_AUTHORING_MANIFEST: ComponentAuthoringManifest;
1469
+
1470
+ export { BulkUploadResultStatus, ErrorCode, ErrorMapperService, FILES_UPLOAD_AI_CAPABILITIES, FILES_UPLOAD_EN_US, FILES_UPLOAD_ERROR_MESSAGES, FILES_UPLOAD_PT_BR, FILES_UPLOAD_TEXTS, FilesApiClient, PRAXIS_FILES_UPLOAD_AUTHORING_MANIFEST, PRAXIS_FILES_UPLOAD_COMPONENT_METADATA, PdxFilesUploadFieldComponent, PraxisFilesUpload, PraxisFilesUploadConfigEditor, PresignedUploaderService, ScanStatus, TRANSLATE_LIKE, acceptValidator, createPraxisFilesUploadI18nConfig, getPrimaryErrorItem, isErrorEnvelope, maxBulkSizeValidator, maxFileSizeValidator, maxFilesPerBulkValidator, providePraxisFilesUploadI18n, providePraxisFilesUploadMetadata, resolvePraxisFilesUploadText };
1469
1471
  export type { ApiErrorEnvelope, ApiErrorItem, ApiResponseStatus, ApiSuccessEnvelope, BulkConfig, BulkUploadFile, BulkUploadFileResult, BulkUploadOptions, BulkUploadResponse, BulkUploadResponseData, Capability, CapabilityCatalog, CapabilityCategory, EffectiveUploadConfig, ErrorLike, ErrorResponse, FileMetadata, FileUploadOptions, FilesUploadBackendOptionsConfig, FilesUploadConfig, FilesUploadExecutionConfig, FilesUploadHeadersConfig, FilesUploadMessagesConfig, FilesUploadQuotaFeedbackConfig, FilesUploadRateLimitFeedbackConfig, FilesUploadReadinessEvent, FilesUploadReadySource, FilesUploadReadyState, FilesUploadStrategy, FilesUploadTexts, FilesUploadValidationConfig, FilesUploadVisualConfig, MappedError, Metadata, PendingFilesState, PraxisFilesUploadI18nOptions, PresignResponse, QuotasConfig, RateLimitConfig, RateLimitInfo, ServerMessages, TranslateLike, UploadOptions, UploadProgressEvent, UploadResponse, UploadResponseData, UploadStartEvent, ValueKind };
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@praxisui/files-upload",
3
- "version": "8.0.0-beta.1",
3
+ "version": "8.0.0-beta.12",
4
4
  "description": "File upload components and services for Praxis UI with presigned and direct strategies, quotas and rate-limit handling.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^20.0.0",
7
7
  "@angular/cdk": "^20.0.0",
8
8
  "@angular/core": "^20.0.0",
9
9
  "@angular/material": "^20.0.0",
10
- "@praxisui/core": "^8.0.0-beta.1",
11
- "@praxisui/dynamic-fields": "^8.0.0-beta.1",
12
- "@praxisui/settings-panel": "^8.0.0-beta.1"
10
+ "@praxisui/core": "^8.0.0-beta.12",
11
+ "@praxisui/dynamic-fields": "^8.0.0-beta.12",
12
+ "@praxisui/settings-panel": "^8.0.0-beta.12"
13
13
  },
14
14
  "dependencies": {
15
15
  "tslib": "^2.3.0"