Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
612fc67
Start Python reference value and runtime capability gate
Oct 27, 2026
f30858c
Add Python detached view preparation and Blob projection boundary
Oct 27, 2026
fd266a8
Validate independent Blob URL lifetimes in prepared views
Oct 27, 2026
9ecf29a
Add graph-scoped physical SQL lease for optional modules
Oct 27, 2026
284a969
Add SQLite Blob catalog binding under native graph owner
Oct 27, 2026
0218aba
Recheck current Blob bindings before Python URL projection
Oct 27, 2026
dd56c39
Package Python Blob reference as an independent optional wheel
Oct 27, 2026
1f540e9
Add optional Python file storage and local authenticated HTTP reads
Oct 27, 2026
319969f
Track Python Blob availability across SQLite bindings
Oct 27, 2026
4e9ef20
Verify authorized Python Blob view against real File HTTP storage
Oct 27, 2026
7eabe9d
Bind File ETags to immutable generations
Oct 27, 2026
e05d892
Add scoped SQLite Blob upload verification to optional wheel
Oct 27, 2026
c7c303a
Add optional Python secure document wire module
Oct 27, 2026
5acb9a0
Assemble optional Python Blob reference module
Oct 27, 2026
a75b38b
Bind Python Blob fields in native graph transactions
Oct 27, 2026
f645667
fix: recheck completed Blob uploads on replay
Oct 27, 2026
752e331
Add SQLite secure document open and accept service
Oct 27, 2026
6217351
Bind sealed document Blob selections on current SQLite graph lease
Oct 27, 2026
63ec20e
Bound total document command bytes with Blob selections
Oct 27, 2026
4ea7dd3
Bind new document child blob selections in SQLite graph
Oct 27, 2026
4116512
Fence expired SQLite Blob upload sessions
Oct 27, 2026
26c144a
Hold SQLite Blob upload owner across object I/O
Oct 27, 2026
a28e796
fix(blob): replay concurrent completed confirmation after SQL owner
Oct 27, 2026
6811c85
fix(blob): recover identical file after upload journal rollback
Oct 27, 2026
c582193
test: verify S3 signed range and expiry against local MinIO
Oct 27, 2026
888273a
fix: replay committed Blob upload writes on original lease
Oct 27, 2026
562f01a
test(blob): verify committed confirmation reply loss
Oct 27, 2026
1f77c88
test(s3): verify atomic create-only against compatible server
Oct 27, 2026
dbb0f70
test(blob): verify SQLite upload through real S3 provider
Oct 27, 2026
369eea2
test(blob): verify S3 graph bind and authorized signed view
Oct 27, 2026
c7418f9
feat(blob): add optional decoded JPEG and PNG verifier
Oct 27, 2026
3d03062
Exercise real JPEG verifier through S3 Blob graph and view gate
Oct 27, 2026
5e35d3a
Add bounded real PDF verifier and S3 Blob upload gate
Oct 27, 2026
054fa23
Add fail-closed S3 version-conditional delete
Oct 27, 2026
ac0e136
Add Python SQLite expired-upload Blob maintenance
Oct 27, 2026
8496251
Fence Python File Blob deletion across processes
Oct 27, 2026
7e75be6
Snapshot trusted Blob retention and collect completed server-stream o…
Oct 27, 2026
6c0a03c
Align secure document Blob selection fixtures with trusted retention
Oct 27, 2026
e2b2156
Fence Python File generation sweeps against writers
Oct 27, 2026
fbcf8d7
test(blob): gate completed retention against real S3
Oct 27, 2026
af99a27
Add optional DOCX and XLSX Blob content verifier
Oct 27, 2026
4058410
Verify parsed Office uploads through S3 Blob graph and view
Oct 27, 2026
b6d6afd
Reject Office XML entity declarations before parsing
Oct 27, 2026
326dd94
Add catalog-driven File generation sweep service
Oct 27, 2026
1e8b2a2
Add optional bounded FFmpeg verifier for MP3 and MP4 uploads
Oct 27, 2026
7dc5b8b
Reject audio-only MP4 and gate real media S3 presentation
Oct 27, 2026
f466b02
feat: compose optional Blob content verifiers by format
Oct 28, 2026
9c546e1
Add sandboxed DOC and XLS verifier to Python Blob wheel
Oct 28, 2026
ab2f0f6
Support Unicode filenames in signed object URLs
Oct 28, 2026
0fa0265
Canonicalize document selection digest with legacy replay
Oct 28, 2026
11d539e
Recheck Blob upload authorization on SQLite transaction lease
Oct 28, 2026
5e6bdf1
Recheck completed upload replay on SQLite lease
Oct 28, 2026
2d156de
test(blob): cover allocated ledger binding and outer rollback
Oct 28, 2026
0a8d386
Build and verify optional reference Python release artifacts
Oct 28, 2026
565a1e1
Verify same-host signed S3 URL refresh after expiry
Oct 28, 2026
2aaf295
Verify release wheels with isolated dependency installs
Oct 28, 2026
af8cee3
Guard expired direct uploads from Blob maintenance
Oct 28, 2026
262acc2
test(blob): verify committed Begin reply loss replay in SQLite
Oct 28, 2026
345ef19
test(blob): verify Confirm rolls back on storage close failure
Oct 28, 2026
27219a5
fix(blob): close upload source once before SQL promotion
Oct 28, 2026
7e0e1f8
Cover ten-format S3 graph-to-retention lifecycle
Oct 28, 2026
3bc7c0a
test(s3): verify native Blob module owner rollback and retention
Oct 28, 2026
1ed8ed4
Test multi-entity native Blob graph rollback
Oct 28, 2026
6d2a613
Test native shared Blob final-unbind File retention
Oct 28, 2026
fcb0fff
test: cover shared Blob final unbind on real S3
Oct 29, 2026
f7d9d34
fix(blob): verify Python business database and catalog assembly befor…
Oct 29, 2026
4c2157d
test(blob): preserve unloaded fields in native ledger updates
Oct 29, 2026
b29bdce
Refs #66: verify durable document recovery under current authority
Oct 29, 2026
319ea4a
Refs #66: verify projection integrity and hidden document field prese…
Oct 29, 2026
1e4f7f0
Refs #66: install declared parser extras in reference release CI
Oct 29, 2026
778391f
fix(release): verify signed Python release tag (#66)
Oct 30, 2026
69723d1
fix(release): preflight all Python project versions on PyPI (#66)
Oct 30, 2026
0aaca24
fix(release): verify exact PyPI distribution hashes after upload (#66)
Oct 30, 2026
e0cb6da
Fence Python legacy Blob mutations with before-row facts
Oct 30, 2026
5b60c27
Reject unsafe raw whitespace in projected Blob URLs
Oct 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
test-vectors/*.tsv whitespace=-blank-at-eol
tests/fixtures/reference-modules/*.doc binary
tests/fixtures/reference-modules/*.xls binary
1 change: 1 addition & 0 deletions .github/workflows/example-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
python-version: '3.10'
cache: pip
- run: pip install -e ".[test,telemetry,object-storage-s3]"
- run: pip install --no-deps -e ./packages/teaql-blob-reference
- name: Start dedicated S3 example fixture
run: |
docker run -d --name teaql-python-example-s3 \
Expand Down
58 changes: 58 additions & 0 deletions .github/workflows/optional-blob-wheel.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Optional reference wheels
on:
pull_request:
push:
branches: [main]
workflow_dispatch:
jobs:
optional-wheel:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: pip
- run: python -m pip install --upgrade build
- run: python -m pip install -e ".[test,object-storage-s3]"
- run: python -m pip install -e "./packages/teaql-blob-reference[image,pdf,office]"
- run: python -m pip install --no-deps -e ./packages/teaql-secure-document-reference
- run: python -m pytest -q tests/provider/sqlite/test_blob_catalog_graph.py tests/provider/sqlite/test_file_blob_storage.py tests/provider/sqlite/test_blob_upload.py tests/provider/sqlite/test_blob_module.py
- run: python -m pytest -q packages/teaql-secure-document-reference/tests
- run: python -m build --wheel --no-isolation --outdir .artifacts/base .
- run: python -m build --wheel --no-isolation --outdir .artifacts/blob ./packages/teaql-blob-reference
- run: python -m build --wheel --no-isolation --outdir .artifacts/secure ./packages/teaql-secure-document-reference
- name: Check wheel isolation
run: |
python - <<'PY'
from pathlib import Path
from zipfile import ZipFile

base = list(Path('.artifacts/base').glob('*.whl'))
blob = list(Path('.artifacts/blob').glob('*.whl'))
secure = list(Path('.artifacts/secure').glob('*.whl'))
assert len(base) == len(blob) == len(secure) == 1, (base, blob, secure)
with ZipFile(base[0]) as wheel:
entries = wheel.namelist()
assert any(name.startswith('teaql/') for name in entries)
assert not any(name.startswith('teaql_blob_reference/') for name in entries)
assert not any(name.startswith('teaql_secure_document_reference/') for name in entries)
with ZipFile(blob[0]) as wheel:
entries = wheel.namelist()
assert any(name.startswith('teaql_blob_reference/') for name in entries)
assert not any(name.startswith('teaql/') for name in entries)
assert not any(name.startswith('teaql_secure_document_reference/') for name in entries)
for module in ('__init__.py', 'module.py', 'mutation_participant.py',
'file_storage.py', 'sqlite_catalog.py', 'upload_service.py'):
name = f'teaql_blob_reference/{module}'
assert name in entries
assert wheel.read(name) == (Path('packages/teaql-blob-reference/src') / name).read_bytes()
with ZipFile(secure[0]) as wheel:
entries = wheel.namelist()
assert any(name.startswith('teaql_secure_document_reference/') for name in entries)
assert not any(name.startswith('teaql/') or name.startswith('teaql_blob_reference/') for name in entries)
for module in ('__init__.py', 'round_trip_reference.py', 'document_round_trip.py'):
name = f'teaql_secure_document_reference/{module}'
assert name in entries
assert wheel.read(name) == (Path('packages/teaql-secure-document-reference/src') / name).read_bytes()
PY
34 changes: 33 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,38 @@ on:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: python -m pip install --upgrade build
- run: python -m pip install --editable ".[test,telemetry]"
- run: python -m pip install --editable "./packages/teaql-blob-reference[image,pdf,office]"
- run: python -m pip install --no-deps --editable ./packages/teaql-secure-document-reference
- name: Verify tag matches package version
run: test "${GITHUB_REF_NAME#python-v}" = "$(python -c 'import importlib.metadata; print(importlib.metadata.version("teaql"))')"
- name: Require a verified signed release tag
env:
GITHUB_TOKEN: ${{ github.token }}
run: python scripts/verify_signed_release_tag.py
- name: Test signed release tag verifier
run: python scripts/test_verify_signed_release_tag.py
- name: Test PyPI version-absence verifier
run: python scripts/test_verify_public_release_absence.py
- run: python -m pytest
- run: python -m build
- run: python -m pytest packages/teaql-secure-document-reference/tests
- run: python -m build --outdir dist .
- run: python -m build --outdir dist ./packages/teaql-blob-reference
- run: python -m build --outdir dist ./packages/teaql-secure-document-reference
- name: Verify exact release wheels and source distributions
run: python scripts/verify-reference-release-artifacts.py dist
- name: Run four isolated consumers from exact wheels
run: python scripts/verify-reference-release-consumers.py dist
- name: Resolve and install exact wheels with declared dependencies in clean environments
run: python scripts/verify-reference-release-dependencies.py dist
- uses: actions/upload-artifact@v4
with:
name: python-distributions
Expand All @@ -31,10 +52,21 @@ jobs:
name: pypi
url: https://pypi.org/project/teaql/
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- uses: actions/download-artifact@v4
with:
name: python-distributions
path: dist/
- name: Reverify exact downloaded distributions
run: python scripts/verify-reference-release-artifacts.py dist
- name: Refuse any occupied PyPI version
run: python scripts/verify_public_release_absence.py dist
- uses: pypa/gh-action-pypi-publish@release/v1
- name: Verify exact public wheel and source distribution bytes
run: python scripts/verify_public_release_absence.py --published dist
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ distinguish implemented source, executed examples, artifact verification and rel

```bash
python -m pip install -e '.[test]'
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src python -m pytest -q
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src:packages/teaql-blob-reference/src python -m pytest -q
PYTHONDONTWRITEBYTECODE=1 bash scripts/verify-examples.sh
```

Expand Down
99 changes: 99 additions & 0 deletions packages/teaql-blob-reference/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# teaql-blob-reference

Optional Blob catalog and current-read services for TeaQL Python. Install this wheel alongside the matching `teaql` version. Catalog migration and runtime service installation are explicit host actions; this package does not install schema or expose routes on import.

`BlobReferenceModule.ready(context)` checks that the current native SQLite
business executor and catalog refer to the same database before activating the
content verifier. The executor's `uses_sql_database` SPI asks the transport for
identity; the native SQLite transport compares SQLite's actual `main` filename
from `PRAGMA database_list`, so ordinary paths and native file URIs can match.
An empty filename cannot establish a durable database for its independent
per-operation connections and is rejected. Missing/non-native owners, a different
dialect or file, and drift between the installed services' catalogs fail with
`BLOB_CAPABILITY_MISSING`. Separate native transports to the same file remain
supported. Installation stays passive; explicit readiness performs metadata
reads, schema validation and verifier readiness without migrating or uploading.

`SqliteBlobUploadService` offers a host-invoked, scope-bound upload journal. The host must provide current model/action authorization and a trusted parser that consumes every stored byte and returns actual format, size, and SHA256. The service writes through the context's object-storage provider, rechecks the stored generation before confirmation, and promotes the row to `uploaded_unbound` only after full verification. The included PDF verifier in tests is a fixture, not a production format parser. Other SQL backends and production ten-format parsing remain open.

For permissions backed by mutable business rows, the host may implement `current_on_lease(actor, lease, target, action, input)` and return `BlobUploadAuthorizationState(scope, field, allowed)`. Begin, Write, and Confirm then recheck that state on the same physical SQLite transaction as the upload journal; a missing row, revoked permission, malformed state, or scope/field mismatch denies the operation. The ordinary `scope`, `field`, and `authorize` callbacks remain the preflight path and the compatibility path for hosts without this optional hook.

To use several optional parsers in one upload service, pass a
`CompositeBlobContentVerifier` with explicit extension-to-parser routes. It
copies and validates the route table at construction, calls each distinct
parser's readiness check once, and rejects unregistered formats before reading
stored bytes. It does not import optional decoder packages or add formats by
itself; install only the image/PDF/Office/media extras the host selects.

For retention-aware uploads, the host may implement `current_policy_on_lease(actor, lease, target)` on its upload authorization and return an immutable `BlobRetentionPolicy`. The service obtains this trusted policy on the physical SQLite begin lease and snapshots its profile, upload mode and retention durations into the catalog. It rejects direct mode on this server-stream path. Confirmation records `completed_at_ms`; replay never changes the accepted policy or completion time. Older rows remain NULL-policy after migration and are excluded from retention collection. A binding authorization must provide its own current policy on the graph lease; new bindings of unknown-policy rows fail closed. Successful binding preserves the longest accepted unreferenced duration and minimum retention deadline. The final unbind records `last_unbound_at_ms` while the row remains `available`, so its lifetime is measured from the actual final unbind. The shared policy vectors are pinned by SHA-256 in the tests.

`SqliteBlobMaintenanceService` is an optional, explicitly host-scheduled service for expired incomplete uploads and policy-backed completed, unbound server-stream objects. It includes formerly bound objects only after the final unbind deadline and retention floor. Active bindings, unknown-policy legacy rows and direct uploads are excluded. The host supplies a current scope and async `can_maintain` policy, then calls `run_batch(context, cursor)` and may install the service through `BlobReferenceModule(..., maintenance=service)`. Run `catalog.ensure_schema()` as a separate migration before readiness; it adds a unique object-key index and nullable policy/time columns. Cleanup claims rows under SQLite `BEGIN IMMEDIATE`, pins the observed ETag, uses only version-conditional storage deletion, and can resume after a failed final catalog acknowledgment. `FileObjectStorage` guards manifest publication and conditional deletion with a persistent per-key OS file lock. Its ETag includes an immutable generation token, so identical-byte replacement cannot match an older version. A matching delete removes the current data generation and manifest. The host may separately call `FileObjectStorage.sweep_old_generations(key)` for a known object key to remove inaccessible older immutable data generations; it waits for same-key writers and preserves the current manifest generation. Use this only after all processes using that private root run a writer-lock-capable version, and schedule/retry it separately from the catalog receipt. Keep each Blob object key unique and immutable, including across manual S3 writes. Direct-upload quiescence and cross-machine S3 retention remain outside this service.

`SqliteBlobFileGenerationSweepService` supplies a separate, host-scheduled
catalog-driven File sweep. After every process sharing the private File root
has upgraded to the writer-lock protocol, the host constructs it with
`all_writers_upgraded=True` and calls `run_batch(actor, provider, cursor)`
outside graph SQL. It pages only the authorized scope's `server_stream` rows,
including `deleted` rows that may retain inaccessible old data generations.
The provider must be the exact `FileObjectStorage` installed in the current
context. Each outcome reports removed generations or a sanitized failure;
restart the scan from the beginning to retry a failed row. Keep terminal
catalog rows until the File sweep has completed. The host assertion cannot
detect an older external writer on its own; no worker or timer starts at import.

For actual JPEG/PNG parsing, install `teaql-blob-reference[image]` and inject
`teaql_blob_reference.content_pillow.PillowBlobContentVerifier`. The image extra
pins Pillow 12.3.0, the newest release supporting Python 3.10 at this checkpoint.
The adapter validates complete JPEG/PNG containers and PNG CRCs, checks the
decoder's real format and loads all pixels with explicit input, pixel and
concurrent-work bounds. It has no hard CPU/process isolation. Construction is
passive; `BlobReferenceModule.ready` invokes its optional decoder readiness check.
It accepts `jpg`, `jpeg` and `png` only. The other formats need separate
production adapters; the earlier PDF fixture test does not establish them.

For actual PDF parsing, install `teaql-blob-reference[pdf]` and inject
`teaql_blob_reference.content_pypdf.PypdfBlobContentVerifier`. The PDF extra
pins pypdf 6.21.3. This adapter checks a complete PDF container with strict
cross-reference parsing, a real page tree and content operators, and bounded
input, pages, decoded page content and concurrent work. It rejects encrypted
PDFs. This is parser validation, not malware scanning or hard CPU/process
isolation. The PDF fixture verifier used in older S3 tests remains test-only.

For actual DOCX/XLSX parsing, install `teaql-blob-reference[office]` and inject
`teaql_blob_reference.content_office.OfficeBlobContentVerifier`. The office extra
pins python-docx 1.2.0 and openpyxl 3.1.5. The adapter checks every ZIP member
and its CRC under input, decoded-byte and part-count limits, rejects XML entity
declarations, checks the expected
Office main content type and package relationship, then parses the Word body or
every Excel worksheet under an element/cell count limit. It hashes original
bytes and returns the precise Office MIME type. Construction is passive, and
`validate_ready` requires both optional parsers. The in-process parsers do not
provide hard CPU or process-memory isolation.

For binary DOC/XLS on Linux, inject
`teaql_blob_reference.content_legacy_office.LegacyOfficeBlobContentVerifier`
with absolute paths to patched LibreOffice (`soffice`), `bwrap`, `prlimit` and
an owner-only (`0700`) canonical scratch directory. Install the `office` extra
for its converted OOXML verifier. The adapter checks original CFB header and
sector layout, converts each file in a network/PID-isolated bubblewrap
namespace with read-only system mounts and only one private writable scratch,
then fully validates the DOCX/XLSX output. CPU, address-space, file-size,
wall-time, input and concurrency limits apply. It returns original DOC/XLS
SHA, size and MIME, so storage keeps the original bytes. This is bounded
decodability verification, not malware or macro detection.

For actual MP3/MP4 validation on POSIX hosts, inject
`teaql_blob_reference.content_ffmpeg.FfmpegBlobContentVerifier` with absolute
paths to trusted `ffprobe` and `ffmpeg` executables. The host installs and
patches those binaries separately; this wheel does not bundle or fetch them.
`validate_ready` checks availability when the module is activated. The adapter
walks complete MP3 frames or top-level MP4 boxes before forcing the matching
FFmpeg demuxer, probing decoded frame counts and stream properties, and fully
decoding media from a pipe. Client filenames and URLs never reach FFmpeg. It
allows only the `pipe` protocol and bounds input bytes, frame count, video
pixels, concurrent checks, child CPU time and address space, and wall time.
The accepted MP3 profile is MPEG Layer III with fixed, non-free bitrate and a
constant sample rate; MP4 must contain a supported `ftyp` brand, `moov`,
`mdat`, and at least one decodable non-cover-art video stream. The adapter returns the SHA-256
of the original bytes and `audio/mpeg` or `video/mp4`. It is content validation,
not malware scanning; ffprobe/ffmpeg themselves must be kept current.
22 changes: 22 additions & 0 deletions packages/teaql-blob-reference/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "teaql-blob-reference"
version = "0.3.1"
description = "Optional TeaQL Blob reference module"
readme = "README.md"
requires-python = ">=3.10"
license = "Apache-2.0"
authors = [{ name = "TeaQL" }]
dependencies = ["teaql==0.3.1"]

[project.optional-dependencies]
image = ["Pillow==12.3.0"]
pdf = ["pypdf==6.21.3"]
office = ["python-docx==1.2.0", "openpyxl==3.1.5"]

[tool.setuptools.packages.find]
where = ["src"]
include = ["teaql_blob_reference*"]
28 changes: 28 additions & 0 deletions packages/teaql-blob-reference/src/teaql_blob_reference/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Optional Blob reference services; the base teaql runtime does not import them."""

from .sqlite_catalog import BlobBindingChange, BlobBindingTarget, BlobCatalogRead, SqliteBlobCatalog
from .read_service import SqliteBlobResponseContributor
from .module import BlobReferenceModule
from .maintenance_service import (BlobMaintenanceAuthorization, BlobMaintenanceBatch,
BlobMaintenanceCursor, BlobMaintenanceOutcome,
SqliteBlobMaintenanceService)
from .mutation_participant import SqliteBlobMutationParticipant
from .file_storage import FileObjectStorage
from .file_generation_maintenance import (BlobFileGenerationSweepBatch,
BlobFileGenerationSweepOutcome,
SqliteBlobFileGenerationSweepService)
from .retention import BlobRetentionPolicy
from .content_composite import CompositeBlobContentVerifier
from .upload_service import (BlobUploadAuthorizationState, BlobUploadInput,
BlobUploadSession, BlobUploadTarget,
BlobVerifiedContent, SqliteBlobUploadService)

__all__ = ["BlobReferenceModule", "SqliteBlobMutationParticipant", "BlobBindingChange", "BlobBindingTarget", "BlobCatalogRead",
"BlobMaintenanceAuthorization", "BlobMaintenanceBatch", "BlobMaintenanceCursor",
"BlobMaintenanceOutcome", "SqliteBlobMaintenanceService",
"BlobFileGenerationSweepBatch", "BlobFileGenerationSweepOutcome",
"SqliteBlobFileGenerationSweepService",
"SqliteBlobCatalog", "SqliteBlobResponseContributor", "FileObjectStorage",
"BlobUploadAuthorizationState", "BlobUploadInput", "BlobUploadSession", "BlobUploadTarget",
"BlobVerifiedContent", "SqliteBlobUploadService", "BlobRetentionPolicy",
"CompositeBlobContentVerifier"]
Loading
Loading