Skip to main content

tom_core_kernel 1.1.16 copy "tom_core_kernel: ^1.1.16" to clipboard
tom_core_kernel: ^1.1.16 copied to clipboard

Core kernel library for the TOM framework containing base modules.

1.1.16 #

This release is built from the repository at the state the entries below describe (an Unreleased section included); its own section is in the full history linked at the end.

Unreleased #

Added #

  • Preference defaults and the bulk write (preferences/). TomUserPreferenceDto.origin (tomUserPreferenceOriginUser 'user', tomUserPreferenceOriginRole 'role', tomUserPreferenceOriginDeployment 'deployment'; default user) and its getter isDefault say whether a value is the caller's own or a default the server answers under a key the caller has not written; listPreferences and readPreference include those defaults, and the read answers preferences.not_found only for a key with neither. TomUserPreferenceBulkWriteRequest (preferences: key → {valueType, value}; .of(writes); writes in key order, refusing a malformed entry as preferences.bulk.malformed = tomUserPreferencesBulkMalformedErrorKey) is the request of the endpoint tomUserPreferencesBulkWriteEndpointId (writePreferences, POST /preferences), which writes the batch all or none and counts its new keys against tomUserPreferencesMaxPerPrincipal together; TomUserPreferencesApiService.writePreferences. doc/preferences/preferences.md § Defaults beneath the caller's own values, § Writing several preferences at once; tests in test/preferences_test.dart.

  • Job priority, pausing and checkpoints (scheduling/). TomJobDefinition.priority and TomScheduledJob.priority (default 0) are copied onto every run the scheduler plans (TomJobRun.priority), and TomJobStore.claimDue takes due runs by descending priority, in queue order among equals. TomScheduler.pauseJob / resumeJob / pausedJobs (store contract pauseJob(jobName, now), resumeJob, pausedJobs) hold a job's runs out of claimDue and backlog on every node sharing the store; a paused clock-driven job is not planned, so on resume its missed windows follow its TomMissedWindowPolicy, and a paused event job's events wait in the queue. TomJobRunContext (current, require(), runId, jobName, checkpoint, saveCheckpoint) lets a running body save an opaque JSON map as its progress (TomJobRun.checkpoint, TomJobStore.saveCheckpoint, fenced on the claim and false once the claim no longer holds the run); the checkpoint is kept across retries and recovery and handed to the next attempt, and recovery still re-queues a started run only when its job sets requestsRecovery. The scheduler dispatches every body inside a TomJobRunCommand, whose port carries a save from a worker isolate back to the scheduler. Error keys schedule.job.checkpoint (not JSON-encodable, TomJobStore.encodeCheckpoint), schedule.job.checkpoint_failed (the store could not write it) and schedule.run_context.missing (require() outside a job body). doc/scheduling/scheduling.md § Priority, § Pausing a Job, § Checkpoints; sample example/samples/scheduling/06_priority_pause_checkpoint_example.dart; tests in test/scheduling_test.dart, test/scheduled_job_test.dart, test/scheduling_error_keys_test.dart and the store contract suite test/contracts/scheduling_contract.dart.

  • HTTP client resilience (http_connection/, resilience.dart): TomResilientClient wraps a package:http client and applies the TomHttpResiliencePolicy of each call's destination (scheme://host:port) — a timeout per attempt (30 s by default), a TomHttpRetryPolicy (3 attempts, jittered exponential backoff from 200 ms to 5 s, Retry-After in seconds honoured up to that ceiling; only for idempotent methods or an Idempotency-Key header, and buffered bodies; on a connection failure, a timeout, 429, 502, 503 or 504), a TomCircuitBreakerPolicy (opens after 5 consecutive errors, timeouts or 5xx, half-opens after 30 s) and a TomBulkheadPolicy (32 concurrent, 64 queued; a permit is held until the response body has been read). Breakers (TomCircuitBreaker, TomCircuitState) and bulkheads (TomBulkhead) are shared per destination across the isolate. TomHttpResilience holds the defaults, per-destination policies (setDestinationPolicy, policyFor), configure for a configuration map (timeoutMs, retry, circuitBreaker, bulkhead, destinations; false / 0 switches a part off), reset and clock for tests. Refusals raise TomHttpResilienceException (http.client.timeout, http.client.circuit_open, http.client.bulkhead_full, http.client.config.invalid). Series tom_http_client_attempts, tom_http_client_retries, tom_http_client_rejections, tom_http_client_circuit_open. doc/http_connection/http_connection.md § Resilience; sample example/samples/http_connection/09_http_resilience_example.dart; tests in test/http_resilience_test.dart.

  • TomTraceContext (context/): the W3C Trace Context a piece of work belongs to, carried in the zone — traceId, spanId, parentSpanId, sampled. parse reads a traceparent header and answers null for an invalid one (as the W3C specification requires), newRoot starts a trace, child continues one with a new span, traceparent renders the header for an outgoing call, and run / current install and read it. The constructor throws FormatException for an invalid id. doc/context/context.md § Trace Context; sample example/samples/context/05_trace_context_example.dart; tests in test/structured_logging_test.dart.

  • Structured log output (logging/): TomJsonLogOutput writes one JSON object per line — timestamp (UTC, ISO 8601), level (lower-case), message, logger, isolate (fixedFields), then the context fields of the current zone — with errors and status to stderr as TomConsoleLogOutput routes them, or through a writer. TomLogContext holds the context fields (trace_id, span_id, tenant by default; register / unregister a TomLogFieldProvider, names, fields()); a provider that throws is skipped, and registering a fixed field name throws ArgumentError. Fixed fields carry ids only, never personal data. doc/logging/logging.md § Structured JSON Output; sample example/samples/logging/07_json_log_output_example.dart.

  • Metrics module (metrics/): TomMetricRegistry holds counters (TomCounter), gauges (TomGauge), histograms (TomHistogram, with tomLatencyBuckets and tomLagBuckets) and observed gauges (observe, TomMetricObserver, TomObservedValue, TomMetricObservation) per isolate; collect() answers a sorted snapshot of TomMetricFamily / TomMetricPoint, and tomPrometheusText renders it in the Prometheus text format 0.0.4 (tomPrometheusContentType). TomMetrics.registry is the registry the framework records into; misuse raises TomMetricsException (metrics.name.invalid, metrics.name.conflict, metrics.label.invalid, metrics.counter.negative). A failing or slow observer is skipped and counted in tom_metrics_observation_failures_total. doc/metrics/metrics.md; samples in example/samples/metrics/; tests in test/metrics_test.dart.

  • Scheduler metrics. TomScheduler records tom_job_start_lag_seconds, tom_job_run_duration_seconds, tom_job_runs_total{job,outcome} and tom_job_last_success_timestamp_seconds, and from start() to close() observes tom_job_backlog and tom_job_backlog_age_seconds for its own registered jobs. doc/scheduling/scheduling.md § Metrics.

  • TomScheduler.started (scheduling/): the schedulers of this isolate that were started and not yet closed, as an unmodifiable snapshot. start() adds a scheduler, close() removes it, stop() leaves it listed. A graceful shutdown stops every one, drains them within its deadline and closes them so their leases are released. doc/scheduling/scheduling.md § The Scheduler; test in test/scheduling_test.dart.

  • TomShutdownCleanup.exitAfterSignalShutdown and exitProcess (shutdown_cleanup/): with the flag set (default false), a shutdown started by a signal calls exitProcess(0) once every phase has run; a shutdown started by calling performShutdown() never exits. exitProcess defaults to dart:io's exit and is replaceable for tests. doc/shutdown_cleanup/shutdown_cleanup.md § Exiting after a signal; sample example/samples/shutdown_cleanup/03_shutdown_execution_example.dart (example 11); tests in test/shutdown_cleanup_test.dart (group exitAfterSignalShutdown).

  • TomJobStore.backlog(now) and TomJobBacklog: the due, unclaimed runs per job — how many, and since when the oldest has been due. A new abstract member: an implementation of TomJobStore outside this package must add it. Implemented by TomMemoryJobStore and TomFileJobStore, and held to the store contract suite.

  • TomItemType.lowestLevelGranting(grade) — the weakest level whose grade is at least grade, the minimum level of a "every item this principal may read (or write)" query. A type whose stronger level stands for a weaker grade is now refused at declaration, so that threshold holds for every level above it. doc/security/security.md § Item Permission Levels.

  • Item permission levels. TomItemType (ordered levels, each mapped to a TomAuthState; standard is view < comment < edit < manage; fromJson reads a manifest declaration), TomItemTypeRegistry and TomItemPermissions (levelOn, allows, gradeOn) in security/item_permissions.dart. Items are named at run time — <type>:<id> — and a level held on a pattern <type>:<prefix>* covers every item whose id starts with the prefix, so a category or folder needs no item list. TomResourceRoleAdapter.resolveAuth resolves an item key through the level's grade, and TomResourceRoleRegistry.stateOn / strongerOn apply the type's grades and order on item keys. doc/security/security.md § Item Permission Levels; tests in test/item_permissions_test.dart.

  • Tenant context in context/tenant_context.dart: TomTenantContext holds the tenant the current zone belongs to (currentId, isSet, run, require, validate, qualify, idPattern — a lower-case identifier of at most 32 characters); TomTenantException raises tenancy.id.invalid and tenancy.context.missing; TomTenantScopedCommand runs a TomCommand inside a tenant wherever it executes, a worker isolate included; TomTenantEvent names the tenant of an event-triggered job's run. A tenant is an isolation boundary and is distinct from the organization, a business unit inside it.

  • TomPrincipal.tenant, written into and read back from the token as the tenant claim by TomBearerAuthentication, independently of organization.

  • Runs of a tenant. TomJobRun.tenant (serialized by toJson / fromJson); TomJobStore.findWindow takes tenant:, so a window is per tenant. TomScheduler records the tenant of a TomTenantEvent, builds and runs the run's body inside the tenant (wrapping the command in a TomTenantScopedCommand), and serialises allowOverlap: false per job and tenant — the cluster lease is job:<name>@<tenant> — so one tenant's run never waits for another's.

  • package:tom_core_kernel/tom_core_kernel_io.dart, the native-only entry library, exporting the file guard the kernel's file-backed stores use: tomWithFileLock, the new tomWithFileLockAsync — the same guard, waiting with Future.delayed so a UI isolate is not blocked — and tomFileLockPath / tomFileLockStaleAfter. The two waiters share one non-blocking acquisition attempt, so they are one lock.

  • lookupObjectInTree in json/map_merge_and_process.dart: the walk behind getObjectFromTree, reporting a path it cannot resolve as (found: false, value: null) instead of throwing. Both now share one walk.

  • Passkey wire types in security/webauthn.dart: TomWebAuthnCreationOptions, TomWebAuthnRequestOptions, TomWebAuthnRegistrationResponse and TomWebAuthnAuthenticationResponse, each serialising to WebAuthn Level 3's JSON form, with toSubmission() / fromSubmission() carrying a response through the second factor's String seam; plus TomWebAuthnUserVerification, TomWebAuthnAlgorithms and the unpadded base64url codec TomBase64Url. Shared by tom_core_server's TomWebAuthn2FAService and tom_core_flutter's passkey mechanism.

Changed #

  • TomFileJobStore writes a JSON object. The queue file is {"runs": [...], "paused": {"<job>": "<ISO instant>"}}; a file holding a bare array is treated as damaged — moved to <queue>.corrupt and started empty.

  • TomDefaultHttpClientFactory.getClient() returns the platform client inside a TomResilientClient. Every TomServerChannel call — and with it every TomServerEndpoint call and TomHttpFileTransferClient transfer — runs under its destination's resilience policy, so an attempt that receives no status and headers within 30 seconds fails with http.client.timeout where it used to wait indefinitely. A custom TomHttpClientAbstractFactory replaces the default whole and wraps its own client to keep the policies. An upload slower than the timeout needs a destination policy with a longer timeoutMs, or 0.

  • The principal id is a string, unique within its tenant. TomUser.id and TomPrincipal.id are String (default TomUser.noId, ''), so a deployment can use a UUID, a directory's object id or a database key rendered as text; the token's userId claim is a string, and a claim of another shape reads as noId. Another tenant may hold the same id — a different person. TomPrincipal.qualifiedId is the id qualified by the principal's tenant, the key per-principal rows are filed under, and TomTenantContext.qualifyCurrent qualifies a name by the tenant in context.

  • TomJobStore.findWindow(jobName, scheduledFor, {String? tenant}) — every store implementation takes the named tenant and matches a window of that tenant only (null matching runs of no tenant). TomMemoryJobStore and TomFileJobStore do.

  • TomPrincipal.organization is documented as the business unit inside the tenant, no longer as the multi-tenant identifier; the tenant is TomPrincipal.tenant.

  • Every sample group runner frames its output the same way, through sampleGroupHeader / sampleGroupFooter in example/sample_bootstrap.dart (Running <Group> Examples... and a rule; the rule and All <Group> examples completed successfully!). Eight runners printed a box-drawn title instead. tool/run_standalone_examples.sh fails a runner that does not use the pair.

  • A resource miss no longer constructs an exception. Both resource providers resolve dotted keys through lookupObjectInTree instead of catching getObjectFromTree's TomJsonPathException. Constructing a TomException renders a stack trace, and under flutter test's stack-chaining zone each render parses the whole chain; since a widget probes a key for every optional colour, style and text, misses dominated widget builds under test — one two-hundred-widget demo screen built in seventy seconds, and tom_flutter_ui_test's overflow suite took about twenty-five minutes. It now runs in about twenty seconds. Lookup results are unchanged.

  • The API summaries moved from doc/api_reference/ to doc/api/, where every other package and the workspace guideline already kept them. The folder held only the markdown summaries and their index; the name api_reference now means only the built PDF, doc/{package}_api_reference.pdf.

  • TomLoginFailure lives here, and a failed TomAuthenticationResult carries it. The enum moved from tom_core_server beside the result, which gains loginFailure (the value's name, on the wire) and a typed loginFailureReason accessor. A client switches on the closed set whether a login failure was thrown (the server's envelope) or returned as a result, without depending on the server package.

  • A mixin scope keeps its path. TomScopeMixin.getScopePath composes the path from the parent's and keeps it once the parent has kept its own (or there is no parent), so on a chain of mixin scopes each path is built once. A parent that is not a TomScopeMixin falls back to buildScopePath on every call, and nothing below it is kept, so a hand-rolled scope whose parent changes is still followed. buildScopePath itself stays uncached.

  • The isolate log sinks take their transport as an interface. TomIsolateLogOutput(TomCommandDispatcher dispatcher) replaces the TomWorkerPool workerPool field; TomWorkerPool implements the new TomCommandDispatcher (execute, close). TomCreatorLogOutput takes an optional TomCreatorChannel channel, defaulting to the new TomCreatorChannel.current (the running isolate's back-channel). Tests now assert all seven fields of the record each sink dispatches, which a level/message transposition at either call site fails.

  • schedule.cron.empty_field is gone. No cron field that parses can match nothing — every item either raises its own key or adds at least the low end of its range — so the raise was unreachable and is removed with its documented entry.

  • Discovered components may take their dependencies through the constructor. Discovery plans every key first and then builds each component through its unnamed constructor, supplying every required parameter — positional or required named — with the bean bound under exactly the parameter's type, building that component first. Construction follows the constructors' dependency order. Three new keys refuse what cannot be built, each naming the class and the parameter: beanlocator.initialization.constructor_dependency_unsatisfied, …constructor_dependency_filtered (the provider is left out by this deployment's @TomEnvironment / @TomPlatform) and …constructor_dependency_cycle. They replace beanlocator.initialization.constructor_takes_arguments. TomBean field handles are unchanged, and remain the form for mutual dependencies.

  • TomBean.withType takes its key as a type argument. It is now static TomBean<B> withType<B extends Object>(B bean) (and overrideWithType<B>), so TomBean.withType<UserService>(impl) compiles only when impl is a UserService. The Type-value forms are renamed withRuntimeType(Type, Object) / overrideWithRuntimeType, unchecked, for a key known only at runtime. installByEnvironment<T> now requires T extends Object. Breaking: every TomBean.withType(X, bean) becomes TomBean.withType<X>(bean), and every generated reflection artifact that captures TomBean must be regenerated. The change found three registrations in this package's own suite that keyed an AnotherService under TestService.

Tests #

  • Every error key the package raises is named by a test. New *_error_keys_test.dart files pin 43 keys across scheduling, HTTP connection, isolate pooling, observables and scope ids, each asserting the exact key. The beanlocator coverage test no longer carries its own "named by a test" check; tool/check_doc_error_keys.py asks it for every package.
  • test/ai_citation_test.dart fails the suite when an artefact of the package cites a document in the AI-state mount. It runs tom_ai/core/tool/check_doc_ai_citations.py over the package through tom_ai/core/tool/package_gate.dart; the rule and its one exemption (the runtime _ai/trail/ directory) are stated in the checker alone.
  • test/formatting_test.dart delegates to the shared guard. The walk, the generated-file exclusion, the coverage floor and the choice of formatter moved to tom_ai/core/tool/package_format_guard.dart, which every package under tom_ai/core shares; the file keeps only this package's floor, landmarks and generated-output flag.

Added #

  • @TomRecommendedField() and TomReflectionInfo.missingRecommendedFields. The softer twin of @TomRequiredField(): a field a bound map should supply, reported under the same rules, for a caller that warns rather than refuses.

Fixed #

  • TomBearerAuthentication.setTokens checks the authentication token's lifetime as well as the authorization token's. It passed only the authorization token to convertTokenPayloadToPrincipal, so an expired authentication token beside a live authorization token was accepted. Both tokens are now passed, and an expired authentication token throws TomTokenLifetimeException and leaves the session as it was.

  • TomServerEndpoint.createApiServerEndpoint<requestType, responseType> accepts a declaration written in TomApiEndpoint's own order. The class declares <ReturnType, RequestType>, but the factory tested for TomApiEndpoint<requestType, responseType>, so every declaration whose two types differed was refused with apis.endpoint.invalid_type_parameters unless it was written backwards. A declaration written backwards to get past the check is now refused; reverse its type arguments.

  • TomClass.setValues deserializes collections of same-named classes. A TomList<X> or TomMap<String, X> member resolved X through singleElementType / mapValueElementType, which see only the runtime collection and so look X up by simple name. Two TomClass subclasses sharing a simple name in different libraries made every such member throw reflector.classmirror.ambiguous_simple_name. X is now read from the member's declaration, and the name lookup is only the fallback for an element type the reflector cannot describe.

  • The internal file guard no longer lets concurrent breakers in together. Breaking an abandoned guard was check-then-delete, and a release deleted whatever guard stood at the path, so several waiters reaching the staleness boundary at once could each delete a fresh guard and hold the file together. Breakers now take turns through a sibling <lock>.break guard (itself cleared once stale), and a writer releases only a guard carrying its own acquisition token. Found by test/file_primitives_test.dart, the first tests of atomic_file.dart and file_mutex.dart on their own.

  • A TomList<TomString> now binds to a multi-select field. getValues() serializes an observable list as a plain List<dynamic>, and a member that holds a whole list as one value — TomObject<List<String>>, which is what every multi-select form field is — rejected it in set, so bind() failed and took the whole form's bind with it. TomClass.setValues now re-types a list for a TomObject<List<E>> member for each primitive E the framework serializes (String, int, double, bool, nullable or not), widening integral elements into List<double> as the scalar rule already did. An element of the wrong type is still refused. See the observable guide, "Lists: A Serialized List Re-Types Into a List-Holding Scalar".

  • Three broken markdown reference links in doc/scope_ids/scope_ids.md. Zone, id and parent were written with dartdoc's square-bracket syntax around a code span, which markdown renders as literal brackets rather than as a link. No anchor existed to point at, so the brackets are gone and the code spans remain.

Earlier entries #

The full history is in the repository's CHANGELOG.md; this file holds the newest entries that fit pub.dev's size limit.

0
likes
140
points
36
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Core kernel library for the TOM framework containing base modules.

Repository (GitHub)

License

BSD-3-Clause (license)

Dependencies

crypto, http, meta, stack_trace, timezone, tom_basics, tom_crypto, tom_reflection, typed_data, yaml

More

Packages that depend on tom_core_kernel