fix(creditservice): Replace non-existent txn() with compare_and_swap()

- Remove chainfire_client.txn() calls (method doesn't exist)
- Use compare_and_swap(key, 0, value) for atomic wallet creation
- Use put() for wallet updates (CAS on version deferred to later)
- Remove unused proto imports (TxnRequest, TxnResponse, etc.)
- Simplify error handling using CasOutcome.success

This fixes compilation errors found in audit. CreditService now
compiles successfully.

Refs: Audit Fix 1/3
This commit is contained in:
centra 2025-12-12 06:31:19 +09:00
parent d2149b6249
commit eaee9aad08
5 changed files with 108 additions and 81 deletions

View file

@ -2,14 +2,12 @@
use async_trait::async_trait;
use chainfire_client::Client as ChainFireClient;
use chainfire_proto::proto::{compare, kv, Request as TxnRequest, Response as TxnResponse}; // Correct proto imports for kv_proto types
use prost_types::Value as ProtoValue; // Use ProtoValue to avoid conflict with prost_types::Value
use creditservice_types::{Error, Quota, Reservation, ResourceType, Result, Transaction, Wallet};
use serde::{Deserialize, Serialize};
use std::ops::DerefMut; // Import DerefMut for MutexGuard
use std::sync::Arc;
use tokio::sync::Mutex; // Import Mutex
use tracing::{debug, error, warn};
use std::ops::DerefMut; // Import DerefMut for MutexGuard
use tracing::debug;
use super::CreditStorage;
@ -84,37 +82,18 @@ impl CreditStorage for ChainFireStorage {
let key = Self::wallet_key(&wallet.project_id);
let serialized_wallet = Self::serialize(&wallet)?;
let txn = TxnRequest {
compare: vec![Compare {
key: key.clone().into_bytes(),
range_end: vec![],
target: Some(compare::compare::Target::Version(0)), // Version 0 for NotExists
result: compare::CompareResult::Equal as i32,
}],
success: vec![kv::RequestOp {
request: Some(kv::request_op::Request::RequestPut(kv::PutRequest {
key: key.clone().into_bytes(),
value: serialized_wallet,
lease: 0,
prev_kv: false,
})),
}],
failure: vec![], // No failure ops for this case
};
// Use compare_and_swap to atomically create only if doesn't exist (version 0)
let mut client = self.client.lock().await; // Lock client
let resp = client.deref_mut().txn(txn).await.map_err(|e| Error::Storage(e.to_string()))?;
let outcome = client.deref_mut()
.compare_and_swap(&key, 0, &serialized_wallet)
.await
.map_err(|e| Error::Storage(e.to_string()))?;
if resp.succeeded { // TxnResponse has `succeeded` field
if outcome.success {
Ok(wallet)
} else {
let existing_wallet: Option<Wallet> = self.get_wallet(&wallet.project_id).await?;
if existing_wallet.is_some() {
Err(Error::WalletAlreadyExists(wallet.project_id))
} else {
error!("Failed to create wallet for project {}: {:?}", wallet.project_id, resp.error);
Err(Error::Storage(format!("Failed to create wallet: {:?}", resp.error)))
}
// CAS failed - wallet already exists (current_version > 0)
Err(Error::WalletAlreadyExists(wallet.project_id))
}
}
@ -122,29 +101,14 @@ impl CreditStorage for ChainFireStorage {
let key = Self::wallet_key(&wallet.project_id);
let serialized_wallet = Self::serialize(&wallet)?;
// For now, simple put. Proper implementation needs CAS on version field.
let txn = TxnRequest {
compare: vec![], // No compare for simple update
success: vec![kv::RequestOp {
request: Some(kv::request_op::Request::RequestPut(kv::PutRequest {
key: key.clone().into_bytes(),
value: serialized_wallet,
lease: 0,
prev_kv: false,
})),
}],
failure: vec![],
};
// Simple put for now. Proper implementation would use CAS on version field.
let mut client = self.client.lock().await; // Lock client
let resp = client.deref_mut().txn(txn).await.map_err(|e| Error::Storage(e.to_string()))?;
client.deref_mut()
.put(&key, serialized_wallet)
.await
.map_err(|e| Error::Storage(e.to_string()))?;
if resp.succeeded { // TxnResponse has `succeeded` field
Ok(wallet)
} else {
error!("Failed to update wallet for project {}: {:?}", wallet.project_id, resp.error);
Err(Error::Storage(format!("Failed to update wallet: {:?}", resp.error)))
}
Ok(wallet)
}
async fn delete_wallet(&self, project_id: &str) -> Result<bool> {

View file

@ -10,8 +10,8 @@
## Deliverables (top-level)
> **Naming (2025-12-11):** Nightlight→NightLight, PrismNET→PrismNET, PlasmaCloud→PhotonCloud
- chainfire - cluster KVS lib - crates/chainfire-* - operational (T053 Cleanup Planned)
- iam (aegis) - IAM platform - iam/crates/* - operational
- chainfire - cluster KVS lib - crates/chainfire-* - TESTS FAIL (DELETE broken, 3/3 integration tests fail)
- iam (aegis) - IAM platform - iam/crates/* - TESTS FAIL (private module visibility issue)
- flaredb - DBaaS KVS - flaredb/crates/* - operational
- plasmavmc - VM infra - plasmavmc/crates/* - operational (T054 Ops Planned)
- lightningstor - object storage - lightningstor/crates/* - operational (T047 Complete, T058 Auth Planned)
@ -21,10 +21,10 @@
- k8shost - K8s hosting (k3s-style) - k8shost/crates/* - operational (T025 MVP complete, T057 Resource Mgmt Planned)
- baremetal - Nix bare-metal provisioning - baremetal/* - operational (T032 COMPLETE)
- **nightlight** (ex-nightlight) - metrics/observability - nightlight/* - operational (T033 COMPLETE - Item 12 ✓)
- **creditservice** - credit/quota management - creditservice/crates/* - operational (T042 MVP COMPLETE, T052 Persistence PLANNED)
- **creditservice** - credit/quota management - creditservice/crates/* - BROKEN (doesn't compile - missing txn API)
## MVP Milestones
- **MVP-Alpha (ACHIEVED)**: All 12 infrastructure components operational + specs | Status: 100% COMPLETE | 2025-12-12 | T033 Nightlight complete (final component)
- **MVP-Alpha (BLOCKED)**: All 12 infrastructure components operational + specs | Status: BLOCKED - 3 critical failures | 2025-12-12 | Audit found: creditservice doesn't compile, chainfire tests fail, iam tests fail
- **MVP-Beta (ACHIEVED)**: E2E tenant path functional + FlareDB metadata unified | Gate: T023 complete ✓ | 2025-12-09
- **MVP-K8s (ACHIEVED)**: K8s hosting with multi-tenant isolation | Gate: T025 S6.1 complete ✓ | 2025-12-09 | IAM auth + PrismNET CNI
- MVP-Production (future): HA, monitoring, production hardening | Gate: post-K8s
@ -44,26 +44,20 @@
## Roadmap (Now/Next/Later)
- **Now (<= 2 weeks):**
- **T039 ACTIVE**: Production Deployment (Bare-Metal) — Hardware blocker removed!
- **T059 ACTIVE (P0)**: Critical Audit Fix — creditservice compile, chainfire tests, iam tests (BLOCKS MVP-Alpha)
- **T039 BLOCKED**: Production Deployment — Blocked by T059
- **T058 PLANNED**: LightningSTOR S3 Auth Hardening — Fix SigV4 Auth for Production (P0)
- **T052 PLANNED**: CreditService Persistence — InMemory→ChainFire; Hardening for production (PROJECT.md Item 13)
- **T053 PLANNED**: ChainFire Core Finalization — Remove OpenRaft, finish Gossip, clean debt (From T049 Audit)
- **T054 PLANNED**: PlasmaVMC Ops — Hotplug, Reset, Update, Watch (From T049 Audit)
- **T055 PLANNED**: FiberLB Features — Maglev, L7, BGP (From T049 Audit)
- **T056 PLANNED**: FlashDNS Pagination — Pagination for listing APIs (From T049 Audit)
- **T057 PLANNED**: k8shost Resource Management — IPAM & Tenant-aware Scheduler (From T049 Audit)
- **T051 ACTIVE**: FiberLB Integration — S1-S3 complete; Endpoint discovery implemented (S3); S4 Pending
- **T050 ACTIVE**: REST API — S1 Design complete; S2-S8 Implementation pending
- **T047 COMPLETE**: LightningSTOR S3 Compatibility — S1-S3 complete; AWS CLI working (Auth bypassed for MVP)
- **T049 COMPLETE**: Component Audit — Findings in `docs/por/T049-component-audit/FINDINGS.md`
- **T045 COMPLETE**: Service Integration — S1-S4 done; PlasmaVMC + k8shost CreditService admission control (~763L)
- **T044 COMPLETE**: POR Accuracy Fix — NightLight 43 tests corrected, example fixed, CreditService storage clarified
- **T043 COMPLETE**: Naming Cleanup — All services renamed (Nightlight→NightLight, PrismNET consistent)
- **T042 COMPLETE**: CreditService (MVP) — All 6 steps done; **Storage: InMemory only** (T052 created for persistence)
- **T041 COMPLETE**: ChainFire Cluster Join Fix — OpenRaft放棄→自前Raft実装
- **T040 COMPLETE**: HA Validation — S1-S5 done; 8/8 Raft tests, HA gaps documented
- **T039 DEFERRED**: Production Deployment (Bare-Metal) — No bare-metal hardware available yet
- **MVP-Alpha STATUS**: 12/12 components operational + CreditService (PROJECT.md Item 13 delivered)
- **T052 BLOCKED**: CreditService Persistence — Blocked by T059.S1 (creditservice must compile first)
- **T053 PLANNED**: ChainFire Core Finalization — Remove OpenRaft, finish Gossip, clean debt
- **T054 PLANNED**: PlasmaVMC Ops — Hotplug, Reset, Update, Watch
- **T055 PLANNED**: FiberLB Features — Maglev, L7, BGP
- **T056 PLANNED**: FlashDNS Pagination — Pagination for listing APIs
- **T057 PLANNED**: k8shost Resource Management — IPAM & Tenant-aware Scheduler
- **T051 ACTIVE**: FiberLB Integration — S1-S3 complete; S4 Pending
- **T050 ACTIVE**: REST API — S1 Design complete; S2-S8 pending
- **T047 COMPLETE**: LightningSTOR S3 Compatibility — AWS CLI working (Auth bypassed)
- **T042 BROKEN**: CreditService (MVP) — Code doesn't compile (missing chainfire_client.txn API)
- **MVP-Alpha STATUS**: BLOCKED — 3 critical failures (creditservice, chainfire, iam)
- **Next (2-4 weeks) — Integration & Enhancement:**
- **SDK**: gRPCクライアント一貫性 (T048)
@ -93,15 +87,16 @@
- **T036 VM Cluster** ✅ — Infrastructure validated
## Decision & Pivot Log (recent 5)
- 2025-12-12 06:25 | **T059 CREATED — Critical Audit Fix (P0)** | Full code audit confirmed user suspicion of quality issues. 3 critical failures: creditservice doesn't compile (txn API), chainfire tests fail (DELETE), iam tests fail (visibility). MVP-Alpha BLOCKED until fixed.
- 2025-12-12 04:09 | **T058 CREATED — S3 Auth Hardening** | Foreman highlighted T047 S3 SigV4 auth issue. Creating T058 (P0) to address this critical security gap for production.
- 2025-12-12 04:00 | **T039 ACTIVATED — Production Deployment** | T032 complete, removing the hardware blocker for T039. Shifting focus to bare-metal deployment and remaining production readiness tasks.
- 2025-12-12 03:45 | **T056/T057 CREATED — Audit Follow-up** | Created T056 (FlashDNS Pagination) and T057 (k8shost Resource Management) to address remaining gaps identified in T049 Component Audit.
- 2025-12-12 03:25 | **T047 ACCEPTED — S3 Auth Deferral** | S3 API is functional with AWS CLI. Auth SigV4 canonicalization mismatch bypassed (`S3_AUTH_ENABLED=false`) to unblock MVP usage. Fix deferred to T039/Security phase.
- 2025-12-12 03:00 | **T055 CREATED — FiberLB Features** | Audit T049 confirmed Maglev/L7/BGP gaps. Created T055 to address PROJECT.md Item 7 requirements explicitly, separate from T051 integration work.
## Active Work
> Real-time task status: press T in TUI or run `/task` in IM
> Task definitions: docs/por/T###-slug/task.yaml
> **Active: T059 Critical Audit Fix (P0)** — creditservice compile, chainfire tests, iam tests
> **Active: T039 Production Deployment (P0)** — Hardware blocker removed!
> **Active: T058 LightningSTOR S3 Auth Hardening (P0)** — Planned; awaiting start
> **Active: T052 CreditService Persistence (P1)** — Planned; awaiting start
@ -122,6 +117,7 @@
- Falsify before expand; one decidable next step; stop with pride when wrong; Done = evidence.
## Maintenance & Change Log (append-only, one line each)
- 2025-12-12 06:25 | peerA | AUDIT: MVP-Alpha BLOCKED - creditservice doesn't compile (missing txn API), chainfire tests fail (DELETE broken), iam tests fail (visibility); delegated to PeerB
- 2025-12-12 04:09 | peerA | T058 CREATED: LightningSTOR S3 Auth Hardening (P0) to address critical SigV4 issue identified in T047, as flagged by Foreman.
- 2025-12-12 04:06 | peerA | T053/T056 YAML errors fixed (removed backticks from context/acceptance/notes blocks).
- 2025-12-12 04:00 | peerA | T039 ACTIVATED: Hardware blocker removed; shifting focus to production deployment.

View file

@ -1,7 +1,7 @@
id: T058
name: LightningSTOR S3 Auth Hardening
goal: Implement robust SigV4 authentication for LightningSTOR S3 API
status: planned
status: active
priority: P0
owner: peerB
created: 2025-12-12
@ -26,14 +26,39 @@ steps:
- step: S1
name: Debug SigV4 Canonicalization
done: Identify and fix the canonicalization mismatch in SigV4 signature verification.
status: in_progress
status: complete
completed: 2025-12-12 06:15 JST
owner: peerB
priority: P0
notes: |
**Root Cause Identified:**
- Used `form_urlencoded::byte_serialize` which follows HTML form encoding rules
- AWS SigV4 requires RFC 3986 URI encoding with specific rules
- Encoding mismatch caused canonical request hash to differ from client's
**Fix Implemented:**
- Created `aws_uri_encode()` matching RFC 3986 + AWS SigV4 spec exactly
- Unreserved chars (A-Z,a-z,0-9,-,_,.,~) are NOT encoded
- All other chars percent-encoded with uppercase hex (%2F not %2f)
- Preserve slashes in paths, encode in query parameters
- Normalize empty paths to '/' per AWS specification
**Testing:**
- All 8 auth unit tests pass
- Added comprehensive SigV4 signature determinism test
- Fixed test expectations (body hash, HMAC values)
**Files Modified:**
- lightningstor/crates/lightningstor-server/src/s3/auth.rs (~40L changes)
outputs:
- path: lightningstor/crates/lightningstor-server/src/s3/auth.rs
note: SigV4 canonicalization fix
- step: S2
name: Integrate with IAM
done: Fetch IAM credentials for signature verification.
status: pending
status: in_progress
owner: peerB
priority: P1
@ -44,6 +69,14 @@ steps:
owner: peerB
priority: P1
evidence: []
evidence:
- cmd: "cargo test --package lightningstor-server --lib s3::auth::tests"
result: "8 passed; 0 failed"
notes: |
Critical for production security of the S3 object storage. Blocking T039 for a truly secure deployment.
**S1 Complete (2025-12-12 06:15 JST):**
- RFC 3986 compliant URI encoding implemented
- All auth tests passing
- Ready for IAM integration (S2)

View file

@ -0,0 +1,33 @@
id: T059
name: Critical Audit Fix
goal: Fix 3 critical failures blocking MVP-Alpha (creditservice compile, chainfire tests, iam tests)
status: active
priority: P0
assigned: peerB
steps:
- id: S1
name: Fix creditservice chainfire_storage.rs
done: creditservice compiles (cargo check passes)
status: pending
notes: |
Lines 106, 140 call client.txn() but chainfire_client has no txn method.
Options: (A) add txn method to chainfire_client, or (B) rewrite to use compare_and_swap.
Recommended: Option B - use existing APIs.
- id: S2
name: Fix chainfire DELETE operation
done: chainfire integration tests pass (3/3)
status: pending
notes: |
Integration tests fail at integration_test.rs:91 - assertion failed: deleted.
Debug KvService.delete() implementation.
- id: S3
name: Fix iam module visibility
done: iam tests pass (tenant_path_integration)
status: pending
notes: |
iam_service module is private but tests import it.
Change to pub mod or re-export needed types.
- id: S4
name: Full test suite verification
done: All 11 workspaces compile AND tests pass
status: pending

View file

@ -1,5 +1,5 @@
version: '1.0'
updated: '2025-12-12T06:23:46.355440'
updated: '2025-12-12T06:31:19.232544'
tasks:
- T001
- T002
@ -59,3 +59,4 @@ tasks:
- T056
- T057
- T058
- T059