Commit Graph

5231 Commits

Author SHA1 Message Date
Zhengchao An 5e0fdaa247 fix(table-catalog): route read_bounded_json_body errors through ApiError to hold s3s ratchet (#5759)
The namespace REST contracts PR (#5745) added 7 new s3_error! invocations in
read_bounded_json_body, pushing the s3s footprint counter from 1687 to 1693
and violating the ratchet baseline.

Replace those calls with ApiError::invalid_request() (gateway-side error
abstraction, rustfs/backlog#1677 F1, rustfs/backlog#1733) and lower the
baseline from 1687 to 1686.

- Add ApiError::invalid_request(message) constructor to rustfs/src/error.rs
- Replace 7 s3_error! calls in read_bounded_json_body with S3Error::from(ApiError)
- Lower S3_ERROR_LINES_BASELINE from 1687 to 1686

Verification:
- make pre-commit: all guard scripts + fmt-check + quick-check passed
- make clippy-check: passed
- cargo test table_catalog + admin handler tests: 406/406 passed
- s3s-e2e: 27/27 passed
2026-08-06 00:34:46 +00:00
唐小鸭 923e35efa0 fix(site-replication): use MinIO-compatible sts-account IAM item type (#5750)
* test(site-replication): expect MinIO sts-account IAM item type

MinIO madmin-go replicates STS credentials with SRIAMItem type
"sts-account" (SRIAMItemSTSAcc), but RustFS emits and accepts only
"sts-credential", so cross-implementation STS replication fails in
both directions (MinIO returns errSRInvalidRequest, RustFS returns
NotImplemented).

Red-light tests:
- pin the outbound AssumeRole replication item type to "sts-account"
  (construction extracted into assume_role_site_replication_item so it
  is testable, behavior unchanged in this commit)
- update the federated identity replication item snapshot to
  "sts-account"
- inbound apply_iam_item must dispatch both "sts-account" and the
  legacy "sts-credential" alias to the STS arm instead of the
  unknown-type NotImplemented fallback

* fix(site-replication): use MinIO-compatible sts-account IAM item type

MinIO madmin-go replicates STS credentials with SRIAMItem type
"sts-account" (SRIAMItemSTSAcc). RustFS emitted "sts-credential" and
accepted only that value inbound, so STS credential replication with
MinIO peers failed in both directions: MinIO rejected RustFS items as
errSRInvalidRequest and RustFS answered MinIO items with
NotImplemented.

- define SR_IAM_ITEM_STS_ACC ("sts-account") and
  SR_IAM_ITEM_STS_ACC_LEGACY ("sts-credential") in rustfs-madmin
- emit "sts-account" from both outbound sites (AssumeRole hook and
  federated identity OIDC hook)
- accept both types inbound; the legacy alias remains permanently for
  mixed-version RustFS rolling upgrades

Token verification and the retry/event mechanism are unchanged.
2026-08-06 08:29:17 +08:00
唐小鸭 733c7b0f67 fix(replication): accept remote target healthCheckDuration nanoseconds (#5754)
* test(replication): accept madmin nanosecond healthCheckDuration payloads

Red-phase TDD tests for P0-7: mc 'replicate add' sends the madmin default
healthCheckDuration=60s as a Go time.Duration nanosecond integer
(60000000000), which RustFS currently rejects as an unsupported field and
would misread as seconds. Also pins the defensive seconds-or-nanos read
for persisted bucket-targets metadata and the capability contract listing
healthCheckDuration as writable.

Currently failing (red):
- remote_target_request_accepts_go_duration_wire_values
- remote_target_request_accepts_legacy_seconds_health_check
- remote_target_health_check_duration_is_declared_writable
- bucket_target_reads_go_nanosecond_durations_defensively
- runtime_capabilities_response_reports_missing_topology_before_storage_init

* fix(replication): accept remote target healthCheckDuration nanoseconds

mc 'replicate add' always sends the madmin default healthcheck-seconds=60
serialized as a Go time.Duration nanosecond integer (60000000000), so the
default mc link-creation path (and 'mc replicate update') failed with
InvalidRequest. Move healthCheckDuration from the unsupported to the
writable remote-target field list; the capability contract in the runtime
capabilities response follows the constants automatically.

Fix the unit mismatch in both directions:
- Request parsing and persisted bucket-targets reads decode the value
  defensively: below 10^7 it is legacy RustFS seconds, otherwise Go
  time.Duration nanoseconds (also covers MinIO-written metadata).
  totalDowntime shares the same wire shape and gets the same handling.
- The list-remote-targets admin response re-encodes only these two fields
  as nanoseconds via a dedicated serialization path, leaving the persisted
  seconds-based wire format untouched for existing readers.

The per-target health-check interval is accepted for mc compatibility but
not yet applied; the heartbeat keeps its global env-configured interval,
and the explicit 'healthcheck' update op stays rejected. disableProxy,
edge, and edgeSyncBeforeExpiry remain explicitly rejected.
2026-08-06 08:27:27 +08:00
唐小鸭 ead419451a fix(replication): send source versionId as query param to remote targets (#5752)
* test(replication): assert remote PUT and multipart initiate carry versionId query

* fix(replication): send source versionId as query param to remote targets
2026-08-06 08:27:23 +08:00
Henry Guo 7211f29498 feat(table-catalog): complete namespace REST contracts (#5745)
* feat(table-catalog): complete namespace REST contracts

* fix(table-catalog): simplify namespace existence guard

* fix(table-catalog): restore migration guard coverage

* fix(table-catalog): preserve encoded namespace segments

* fix(table-catalog): reject implicit namespace creates

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: Henry Guo <marshawcoco@users.noreply.github.com>
Co-authored-by: houseme <housemecn@gmail.com>
Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-05 21:07:30 +00:00
唐小鸭 04722caa04 fix(madmin): accept MinIO PascalCase SRInfo fields and nil-map nulls (#5749)
* test(madmin): add MinIO PascalCase SRInfo fixture coverage

* fix(madmin): accept MinIO PascalCase SRInfo fields via serde alias

* test(madmin): cover MinIO nil-map SRInfo JSON output

* fix(madmin): tolerate Go nil-map null in SRInfo deserialization
2026-08-06 04:18:05 +08:00
唐小鸭 066e952df1 fix(site-replication): send peer join to MinIO peer/join route with encrypted payload (#5748)
* test(site-replication): pin peer join wire path to MinIO peer/join route

MinIO only ever registered PUT /minio/admin/v3/site-replication/peer/join;
the /site-replication/join path never existed upstream. Flip the wire-path
and payload-encryption expectations to the real MinIO route. These tests
fail until the outbound rewrite is fixed.

* fix(site-replication): send peer join to MinIO peer/join route with encrypted payload

MinIO only registers PUT /minio/admin/v3/site-replication/peer/join; the
/site-replication/join path never existed upstream, so the outbound join
special-case rewrote requests to a 404 route. Drop the special case so
peer join falls into the generic /rustfs -> /minio prefix rewrite, and
move the payload-encryption predicate to the peer/join route (MinIO's
SRPeerJoin force-decrypts the request body).

MinIO also replies with an empty body on a successful join, which the
previous strict JSON parse rejected. Tolerate an empty/whitespace body by
synthesizing the peer identity from the add preflight metainfo
(deployment id) already fetched for the site.

Inbound dual-path registration (join and peer/join under both admin
prefixes) is intentionally unchanged for rolling upgrades from older
RustFS peers that still send the legacy outbound path.
2026-08-06 04:15:35 +08:00
唐小鸭 ea8dbf49a2 fix(auth): route ListBuckets denial through ApiError to hold s3s ratchet (#5755)
fix(auth): route ListBuckets auth denial through ApiError to keep s3s ratchet at baseline

PR #5726 added one s3_error! call in authorize_request while PR #5739 froze
the s3_error! line baseline at 1686 counted before that merge, so a clean
main-derived branch fails the s3s footprint ratchet with +1.

Replace the new macro call with ApiError::access_denied().into(), a small
constructor on the gateway-side error abstraction (rustfs/backlog#1677 F1,
rustfs/backlog#1733) instead of raising the baseline. The converted S3Error
carries the identical AccessDenied code and "Access Denied" message, and the
filtered ListBuckets fallback matches on the code only.
2026-08-06 03:22:28 +08:00
Zhengchao An 5f3bc617fe fix: bump s3_error! footprint baseline to 1687 for auth ListBuckets fix (#5747) 2026-08-06 00:05:01 +08:00
hector 6f10ca18a9 feat(ci): add DEB/RPM packaging workflow (#5738) 2026-08-05 16:19:42 +08:00
Zhengchao An 759ade4770 fix(auth): restore filtered ListBuckets fallback (#5726) 2026-08-05 15:21:51 +08:00
Zhengchao An db1daaece2 ci(scripts): add s3s footprint ratchet ahead of s3gate migration (#5739)
Freeze the direct s3s dependency surface with a lower-only ratchet so it
cannot grow while the s3gate/gateway migration shrinks it
(rustfs/backlog#1677 review finding F1; acceptance criteria in
rustfs/backlog#1733). Baselines verified on 2026-08-05: 236 files
importing s3s, 1686 s3_error! invocation lines. Wired into make
pre-commit / pre-pr / dev-check and the Quick Checks job in ci.yml and
its ci-docs-only.yml mirror.
2026-08-05 15:21:35 +08:00
houseme f0c4fbd28f chore(deps): refresh mimalloc revision (#5736)
* chore(deps): refresh mimalloc revision

Update mimalloc and libmimalloc-sys to the requested git revision after running the dependency refresh flow.

Keep ratelimit excluded while accepting compatible dependency updates from cargo update and cargo upgrade.

Harden all-feature test compilation by giving heavy integration test crates their own recursion limit and avoiding a cross-thread spawn for the embedded startup barrier future.

Co-Authored-By: heihutu <heihutu@gmail.com>

* upgrade version

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-05 04:46:13 +00:00
Zhengchao An 8550a8f9c3 refactor(ecstore): unify remaining heal logs to structured event style (#5720)
PR #5719 fixed the issue #5716 per-object heal log amplification (per-object statements demoted, heal spans forced to TRACE, raw metadata dumps banned by guardrail) and superseded the demotion originally proposed here. This PR now carries only the residual cleanup on top of it:

- Convert the remaining bare-field and format-arg heal logs in crates/ecstore/src/set_disk/ops/heal.rs to the file's structured convention (event/component/subsystem + context fields): missing-object skip, disk-marked-for-healing, cannot-reconstruct errors, dangling-cleanup error, missing data_dir error, xl.meta regeneration warn, and orphan-reclaim failure warn.
- Demote the last remaining info! in the file — the per-set heal_format "set disk formats success, NoHealRequired" no-op message — to a structured debug! (error_count instead of a raw errs dump), and drop its whitelist exclusion in scripts/check_logging_guardrails.sh so the no-INFO check for set-disk heal files is strict.

No control flow or behavior changes.
2026-08-05 03:54:27 +00:00
Zhengchao An 018f27d1cd test(ecstore): deflake multipart listing tests under plain cargo test (#5730)
Multipart upload ids embed the process-global deployment id at both create time and list time. Under plain cargo test (thread-parallel, shared process globals) a concurrently running test that re-initializes a store can swap the global between the two reads, making full-upload-id equality assertions fail spuriously (observed: core::sets::tests::list_multipart_uploads_merges_all_sets_without_pagination_loss failing when run concurrently with bucket::quota tests, passing in isolation).

Add a test-only upload_uuid_suffix helper next to deployment_upload_id and make the affected assertions compare only the decoded <uuid>x<timestamp> suffix. Where suffix normalization changes within-key ordering (base64 alphabet order is not byte order), both sides are sorted before comparison. nextest/CI is unaffected (process-per-test); this only hardens local plain cargo test runs.
2026-08-05 11:50:29 +08:00
Zhengchao An 6617708faa fix(ecstore): make local disk map initialization replace stale topology (#5734)
initialize_local_disk_maps appended pool entries to local_disk_set_drives and inserted into local_disk_map without ever clearing previous state. Every caller (both production startup entry points and all tests) passes the FULL topology, so re-initializing the same InstanceContext left the pool/set vectors sized for the stale topology and panicked with index-out-of-bounds for wider disk indices.

This surfaced as deterministic cross-test contamination under single-process cargo test: in crates/heal heal_b920_subquorum_union_test, a 4-disk test initialized pool 0 as [None; 4] on the process-level default context, and the two 8-disk tests then panicked at disk_idx 4. Each test passed alone, and CI never caught it because cargo nextest isolates every test in its own process.

Fix: clear both registries at the start of initialize_local_disk_maps so initialization is idempotent and last-topology-wins. Add a regression unit test in ecstore (process-isolation-proof, unlike the heal integration binary) that re-initializes the same context with a wider topology; it fails with the pre-fix code.
2026-08-05 11:50:11 +08:00
Zhengchao An f73054f6ad fix(s3): degrade multipart listings per upload instead of failing the bucket (#5721)
The multipart staging namespace is one flat set of sha256(bucket/object) directories shared by every bucket, and the cross-set listing rewrite reads every upload's metadata. Two shapes poisoned the whole ListMultipartUploads response with InternalError: Corrupted format: a healthy in-flight upload belonging to another bucket (its stored owner bucket fails the guard and fell into the corrupted-format arm), and a single upload directory whose xl.meta was torn by an unclean shutdown. Docker Distribution calls ListMultipartUploads on every PATCH/commit, so either shape broke OCI registry pushes entirely (issue #5716).

Foreign-bucket uploads are now skipped silently, and directories whose metadata is affirmatively corrupt at quorum are skipped with a debug log, while every other decode failure (quorum loss from offline disks, timeouts, transport errors) keeps failing the listing so clients retry instead of silently losing entries. The degrade-vs-propagate decision is a named corrupt-family classifier with a unit test pinning both sides. FileMeta::check_xl2_v1 now classifies a missing or wrong XL2 magic as FileCorrupt instead of an anonymous io error so damage is distinguishable from transient IO faults.

Refs #5716
2026-08-05 03:49:52 +00:00
Zhengchao An 8c9e884cf2 fix(ecstore): make inline-rollback reclamation file-precise to keep #5703's child-key safety (#5732)
#5724 reclaimed the synthetic inline-rollback dir after a committed rename with delete_data_dir(recursive: true), which has no notion of object metadata: for unversioned objects the synthetic UUID is a fixed, publicly-known constant, so object/<rollback-dir> can simultaneously be a legitimate child key's directory, and recursively deleting it reopens the authorization bypass #5703 closed (PutObject on K destroying K/<uuid> without DeleteObject permission).

Replace the recursive pass with a file-precise one: after quorum commit, delete exactly object/<rollback>/xl.meta.bkp with a non-recursive delete on every disk whose rollback dir is not also the cleanup dir. The parent-rmdir walk removes the dir only when the backup was its sole content, so the BucketNotEmpty leak fix is preserved (#5724's regression test passes unchanged) while a child key at the same path keeps its metadata. The undo path's restore_metadata_backup now also reclaims the emptied synthetic dir, mirroring restore_delete_rollback.
2026-08-05 03:32:41 +00:00
Zhengchao An 75d0c8d6b9 fix(quota): keep the degraded-baseline fallback off the write path's stack (#5728)
The fallback future embeds the whole snapshot loader, and every object write nests a quota check several futures deep, so inlining it grew each write's state machine by the loader's full size — the debug-build 2MiB worker-stack overflow class fixed for bucket-config writes in #5648. Box the fallback at its call site; the allocation only happens on the degraded path.
2026-08-05 03:02:33 +00:00
Zhengchao An d2e5346044 fix(heal): demote per-object heal logs and cap erasure-set failure warns (#5727)
fix(heal): demote per-object logs and cap erasure-set failure warns

Follow-up to rustfs/rustfs#5716. Per-object heal task kinds (Object/Metadata/MRF/ECDecode) queued by MRF/autoheal/scanner loops emitted info!/warn!/error! lines per object: task lifecycle (started/completed/timed_out/failed), the missing-object warn, queue admission full/drop/displacement warns, retry-admission decisions, and uncapped per-object warns in erasure-set sweeps.

Add a shared demote_to_debug_when! macro that keeps aggregate task kinds and admin/internal requests at operator-visible levels while demoting per-object occurrences to debug!, sample-cap the erasure-set transient_skip/failed warns per bucket via take_failure_log_sample (reusing the heal_bucket_objects precedent), demote the per-retry admission decision logs to debug! (covered by rustfs_heal_admission_total and the scheduler task_retrying/task_failed events), and record the previously unmetered duplicate-admission outcome.

Extend scripts/check_logging_guardrails.sh with injection-verified regression guards and run it in both quick-checks jobs (ci.yml and its ci-docs-only.yml mirror).
2026-08-05 02:43:57 +00:00
Zhengchao An 204068e07e fix(targets): surface redacted construction error detail in target failures (#5729)
A failed target construction previously logged only reason=construction_failed and pushed an opaque "target construction failed" summary, discarding the underlying TargetError. Debugging rustfs#5115 showed the log repeated every 5s with no root cause, even though the error carried an actionable egress-policy rejection (RUSTFS_OUTBOUND_ALLOW_ORIGINS hint).

The Err branch now includes the error detail in both the error! log (detail field) and the returned failures summary. The detail is scrubbed against the instance's merged config via the loader's existing per-field redaction (secrets -> ***redacted***, endpoint URLs -> origin only, DSNs -> password masked) so credential-bearing values never reach logs or Admin-visible summaries.
2026-08-05 02:42:04 +00:00
anthonymartin ec135f8c4c fix(heal): bound per-object logging (#5719)
Co-authored-by: Anthony Martin <949506+anthonymartin@users.noreply.github.com>
2026-08-05 02:25:59 +00:00
Zhengchao An 5bd28048d5 fix(filemeta): redact sealed keys and elide inline data in FileInfo Debug (#5725)
FileInfo's derived Debug printed the full metadata map (including X-Rustfs/X-Minio-Internal-Server-Side-Encryption-Sealed-Key and -Iv values, i.e. KEK-wrapped DEK ciphertext) and the full inline data bytes (plaintext user content for non-SSE small objects), so any whole-struct log dump such as the heal_object dumps leaked user data and sealed key material into logs.

Replace the derive with a manual Debug impl that redacts encryption metadata values (keys stay visible, values print as redacted with length) under both internal prefixes, and elides data/checksum bytes to a length summary. The exhaustive destructuring forces every future field through an explicit show/redact decision. starts_with_ignore_ascii_case is made pub in rustfs-utils for reuse.
2026-08-05 02:07:01 +00:00
Zhengchao An 53a8e02a08 fix(ecstore): reclaim synthetic inline-rollback dirs after rename commit (#5724)
#5703 split rollback state from old-data-dir cleanup so the synthetic inline-rollback dir is reported only as rollback_data_dir and never reclaimed as if it were a real data dir. But nothing reclaims it after a successful commit either: every overwrite of an inline version by a non-inline one leaves <object>/<rollback-dir>/xl.meta.bkp behind. The residue is not referenced by any version, so it survives object deletion and DeleteBucket fails with BucketNotEmpty forever — the mass teardown cascade currently failing the S3 Implemented Tests CI lane.

Reclaim the synthetic dirs in SetDisks::rename_data once the commit holds write quorum. The quorum-failure undo inside the same function is the only consumer of the backup, so its window is closed at that point. Best-effort with the same anti-misdelete posture as commit_rename_data_dir: never touch the just-committed data dir, and residue must not fail a durable write (backlog#898).
2026-08-05 02:04:46 +00:00
唐小鸭 15b9c1f4e3 fix(replication): make bucket replication rules editable from clients (#5715)
* fix(replication): accept explicit STANDARD destination storage class

The replication engine never reads Rule.Destination.StorageClass (replica
placement comes from the bucket-target config or the source object), yet the
validator rejected any config carrying the field. The console's add-rule form
always sends StorageClass=STANDARD, so every rule created through it failed
with InvalidRequest.

Tolerate exactly STANDARD as a no-op — semantically identical to omitting
the field — and keep rejecting every other value, which would be silently
ignored rather than honored. Document the deliberate omission from the
replication capability contract.

* feat(admin): support MinIO-style partial updates for set-remote-target

set-remote-target?update=true previously replaced every stored field and
required complete credentials in the body, so flipping a target's sync mode
from the console forced operators to re-enter the secret key, and real
mc replicate update bodies (madmin Clone() strips the secret) failed to
deserialize at all.

Adopt MinIO's TargetUpdateType contract: query params creds/sync/bandwidth/
path name the field groups to overlay onto the stored target, everything
else keeps its persisted value, and unsupported groups (proxy, healthcheck,
edge, edgeSyncBeforeExpiry) fail loudly. Credentials updates are skipped for
site-replication peer targets — probed by both scheme derivations of the
stored endpoint and the stored deployment id — because an operator never
knows the site replicator's credentials, and a body-supplied deployment id
is ignored on update since it anchors peer identity. madmin JSON aliases
(bandwidthlimit, storageclass, resetID, deploymentID, sessionToken) let mc
bodies parse under deny_unknown_fields.

e2e: cover a credential-free sync-only update preserving the stored
connection and the zero-ops no-op contract; align the missing-arn assertion
with the earlier validation error.

* chore(scripts): add two-site replication lab manager

site_replication_smoke.py spawns and manages two local rustfs processes,
pairs them via the site-replication admin API (idempotent), and verifies
bidirectional object replication. Subcommands: up/down/restart/status/logs/
smoke/info/remove/clean. Stdlib-only; requests are SigV4-signed the same
way as crates/e2e_test.

* chore(scripts): rename direction-suffixed payload variables for typos check

The typos linter reads the _ba suffix in payload_ba as a misspelling of
"by"; use payload_a_to_b / payload_b_to_a instead.

---------

Co-authored-by: overtrue <anzhengchao@gmail.com>
2026-08-05 01:50:31 +00:00
Zhengchao An 4042bc0a5e fix(quota): admit writes against a persisted usage baseline while authoritative usage is unavailable (#5722)
Upgrading from a pre-v2 release leaves only the legacy .usage.json snapshot, which has no completeness marker and is demoted to non-authoritative, so every write to a quota-enabled bucket failed closed with a retryable 503 until the scanner's first complete cycle persisted .usage.v2.json — a production outage on large namespaces (issue #5716).

Quota admission now degrades to the last persisted per-bucket size: normalize_loaded_data_usage returns the pre-discard bucket sizes, the TTL-bounded snapshot cache retains them (carried forward through failed refreshes), and QuotaChecker::get_real_time_usage falls back to that baseline when the authoritative caches miss. The baseline is static between snapshot loads, so hard-quota enforcement is advisory for the duration of the degraded window — strictly tighter than beta.11 (usage treated as 0) and strictly more available than a blanket 503. Buckets absent from every persisted snapshot still fail closed, and removing a bucket's usage from the backend purges the baseline so a recreated bucket cannot inherit the dead incarnation's size.

Refs #5716
2026-08-05 01:42:09 +00:00
Zhengchao An 4576c2e470 fix(iam): invalidate peer STS caches on revocation (#5718) 2026-08-05 01:17:36 +00:00
Zhengchao An 327fdd5fc2 fix(replication): report FAILED when replication put options cannot be built (#5717)
Both per-target replication methods assign the optimistic Completed status to rinfo before building put options, and the Err branch of replication_put_object_options returned rinfo unchanged. Since #5633 made the source encryption classification case-insensitive, managed SSE sources are rejected at this gate, and the rejection was reported as successful replication: the source object was marked COMPLETED, ObjectReplicationComplete was emitted, and nothing existed on the target.

Set replication_status = Failed (and record the error in the replicate_object branch) so the composite status, the OperationFailedReplication event, and MRF retries reflect the fail-closed outcome. This restores the contract pinned by test_bucket_replication_sse_kms_failure_contract, which timed out in the e2e-replication-nightly runs on 2026-08-03 and 2026-08-04.
2026-08-05 01:08:11 +00:00
houseme 16c2928965 refactor(metrics): migrate scanner report timestamps to jiff (#5710)
* refactor(metrics): migrate scanner report timestamps to jiff

Co-Authored-By: heihutu <heihutu@gmail.com>

* refactor(madmin): migrate admin timestamps to jiff (#5712)

Co-authored-by: heihutu <heihutu@gmail.com>

* refactor(storage): migrate RPC DTO timestamps to jiff (#5713)

Co-authored-by: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-04 18:35:38 +00:00
houseme 3dabac4a09 perf(observability): avoid cgroup path allocation (#5711)
* perf(observability): avoid cgroup path allocation

Co-Authored-By: heihutu <heihutu@gmail.com>

* test(e2e): satisfy regression test clippy

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-04 17:47:07 +00:00
Zhengchao An 15c2bade5f fix(iam): disambiguate OIDC virtual parent IDs (#5700) 2026-08-04 23:21:36 +08:00
Zhengchao An 624a4ab837 test(e2e): add P0/P1 regression tests for recurring issue patterns (#5709)
Add 21 E2E regression tests across 7 new test files covering the most
frequently regressing issue patterns identified from 5600+ issues in
rustfs/rustfs. Each test references specific regression issue numbers
and validates the exact failure path that caused the regression.

Regression categories covered:
- P0: Event notification startup race (rustfs#5387, #5681, #5401)
- P0: Lifecycle/ILM rule persistence (rustfs#5407, #5167, #4963)
- P0: Delete consistency (rustfs#5375, #4978, #760)
- P1: Listing completeness (rustfs#4810, #5051, #3191)
- P1: Bucket statistics accuracy (rustfs#5615, #3898, #1012)
- P1: Distributed startup quorum (rustfs#5655, #2945)
- P1: Tier/scanner persistence (rustfs#5218, #5013)

Ref: https://github.com/rustfs/backlog/issues/1670
2026-08-04 23:21:01 +08:00
lqb 4f43c0ca7e fix(compose): set log directory and wait for permission helper (#5646)
* Update docker-compose-simple.yml

Added RUSTFS_OBS_LOG_DIRECTORY=/app/logs in docker-compose-simple.yml

Signed-off-by: lqb <lqb@users.noreply.github.com>

* Added missing dependency to volume-permission-helper

Signed-off-by: lqb <lqb@users.noreply.github.com>

---------

Signed-off-by: lqb <lqb@users.noreply.github.com>
Co-authored-by: houseme <housemecn@gmail.com>
Co-authored-by: cxymds <cxymds@gmail.com>
2026-08-04 23:20:55 +08:00
houseme 3405b4e980 perf(observability): avoid sampler stat allocations (#5708)
* perf(observability): avoid cgroup stat key allocations

Replace the memory.stat HashMap parser with a fixed-field parser so the memory observability sampler does not allocate String keys or hash every cgroup field on each interval.

Co-Authored-By: heihutu <heihutu@gmail.com>

* perf(observability): parse mimalloc stats without copying

Parse the mimalloc stats JSON while the mimalloc-owned buffer is still alive, then free it immediately. This avoids allocating an owned String on each allocator memory sample.

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-04 23:20:49 +08:00
houseme 510b0350d6 refactor(time): migrate audit and notify timestamps to jiff (#5707)
* refactor(time): migrate audit and notify timestamps to jiff

Co-Authored-By: heihutu <heihutu@gmail.com>

* test(ecstore): initialize heal walk decode error

Co-Authored-By: heihutu <heihutu@gmail.com>

* refactor(targets): parse MySQL event time with jiff

Preserve MySQL DATETIME(6) wall-time formatting for RFC3339 eventTime values while removing the direct chrono dependency from rustfs-targets.

Co-Authored-By: heihutu <heihutu@gmail.com>

* chore(deps): prune unused workspace dependencies

Apply cargo shear --fix to remove unused path-clean and s3select-api tempfile entries after the scoped jiff migration.

Co-Authored-By: heihutu <heihutu@gmail.com>

* test(ecstore): remove duplicate heal walk decode error init

Remove the duplicate decode_error field from the heal walk test collector initializer so lib-test clippy compiles on CI.

Co-Authored-By: heihutu <heihutu@gmail.com>

* refactor(policy): emit OPA timestamps with jiff

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-04 23:20:44 +08:00
Zhengchao An b14805af47 fix(ci): block PR-controlled execution in performance A/B workflow (#5705)
fix(ci): block PR execution in performance workflow
2026-08-04 23:20:40 +08:00
Zhengchao An f3eba31aee fix(ecstore): retain namespace read locks for streaming GETs to prevent quota-bypass (#5699)
* fix(ecstore): retain locks for streaming GETs

* fix(rpc): keep disabled snapshot leases lint-clean
2026-08-04 23:20:35 +08:00
Zhengchao An 42af6e3b63 fix(ecstore): isolate inline rollback cleanup (#5703) 2026-08-04 23:20:29 +08:00
Zhengchao An a43267160d fix(auth): enforce object-lock actions for POST uploads (#5701) 2026-08-04 23:20:24 +08:00
Zhengchao An 2039ba5f65 fix(s3select): enforce SSE-KMS read authorization (#5698)
* fix(s3select): enforce SSE-KMS read authorization

* fix(app): route select SSE auth through facade
2026-08-04 23:20:19 +08:00
Zhengchao An 3a6f630ff1 fix(api): bound bucket rate limiter keys (#5706) 2026-08-04 15:13:25 +00:00
Zhengchao An 1695873e55 fix(auth): isolate embedded IAM contexts (#5704) 2026-08-04 23:12:35 +08:00
Zhengchao An c26419e357 fix(replication): restrict metadata replication targets (#5696) 2026-08-04 22:46:42 +08:00
Zhengchao An d401c65719 fix(policy): require unscoped KMS bundle grants (#5697) 2026-08-04 22:46:14 +08:00
cxymds eb87bb1faf fix(replication): harden resync and MRF recovery (#5694)
* fix(replication): harden resync and MRF recovery

* fix(replication): correct MRF validation regressions

* fix(replication): address CI validation failures

* fix(heal): initialize decode error in merge test
2026-08-04 13:40:50 +00:00
houseme 93fcd6b6b5 fix(observability): fallback mimalloc requested memory stats (#5695)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-04 21:10:29 +08:00
Zhengchao An c63dba7d3f fix(list): skip delete markers in single-object fast path for ListObjects (#5691) 2026-08-04 12:49:45 +00:00
cxymds 31959b90db fix(heal): harden resumable set repair failures (#5693)
* fix(heal): enforce resumable task control

* fix(ecstore): surface bucket and metadata heal errors

* chore: refresh guardrail path references

---------

Signed-off-by: cxymds <cxymds@gmail.com>
2026-08-04 12:35:58 +00:00
Zhengchao An 3c8bd5b929 fix(heal): surface stale versions from all disks during heal walk (#5692)
When a returning node carries a stale object version that was deleted on
the quorum, the heal disk-walk partial callback used `resolve_union`
which picks only one entry from divergent disk entries. The minority
version was never enumerated and therefore never cleaned up.

Replace `resolve_union` + `ingest` with a new `ingest_merged` that
collects all unique versions from every partial entry across disks,
deduplicating by (name, version_id). This ensures stale data on a
returning node is surfaced for healing and can be deleted as dangling.

Fixes #5029
2026-08-04 12:18:43 +00:00
Zhengchao An ec106548ba test(e2e): restore webhook redelivery regression coverage (#5690)
test(e2e): unquarantine webhook redelivery regression
2026-08-04 20:00:54 +08:00