Skip to content
13 changes: 8 additions & 5 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,32 @@ managed:
path: .
plugins:
# ===========================================================================
# Go Backend Generation
# Go Backend Generation (LOCAL binaries installed via `go install`).
# buf.build remote plugins were unreachable during S7; local binaries remove
# the runtime dependency on the BSR. To revert, swap each
# `local: protoc-gen-XXX` back to `remote: buf.build/<owner>/<plugin>`.
# ===========================================================================

# Go protobuf structs
- remote: buf.build/protocolbuffers/go
- local: protoc-gen-go
out: ../goapps-backend/gen
opt:
- paths=source_relative

# gRPC service stubs
- remote: buf.build/grpc/go
- local: protoc-gen-go-grpc
out: ../goapps-backend/gen
opt:
- paths=source_relative

# gRPC-Gateway for REST API
- remote: buf.build/grpc-ecosystem/gateway
- local: protoc-gen-grpc-gateway
out: ../goapps-backend/gen
opt:
- paths=source_relative

# OpenAPI/Swagger documentation
- remote: buf.build/grpc-ecosystem/openapiv2
- local: protoc-gen-openapiv2
out: ../goapps-backend/gen/openapi

inputs:
Expand Down
111 changes: 111 additions & 0 deletions finance/v1/cost_attachment.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
syntax = "proto3";

package finance.v1;

import "buf/validate/validate.proto";
import "common/v1/common.proto";
import "google/api/annotations.proto";

// =============================================================================
// CostAttachment — PRD Phase A §7.1.10 (CA_).
// Generic file attachment that hangs off either a request OR a comment (XOR).
// Storage: MinIO via finance.internal/infrastructure/storage. The proto carries
// raw bytes on upload (max 25MB per FR-5); download is via presigned URL.
// =============================================================================

message CostAttachment {
int64 attachment_id = 1;
int64 request_id = 2; // set when request-level
int64 comment_id = 3; // set when comment-level
string filename = 4;
string mime_type = 5;
int64 size_bytes = 6;
string storage_key = 7;
string uploaded_by = 8;
string uploaded_at = 9;
}

// =============================================================================
// Upload
// =============================================================================

message UploadCostAttachmentRequest {
// Exactly one of (request_id, comment_id) must be > 0.
int64 request_id = 1;
int64 comment_id = 2;
Comment on lines +33 to +35
string filename = 3 [(buf.validate.field).string = {
min_len: 1
max_len: 255
}];
string mime_type = 4 [(buf.validate.field).string = {
min_len: 1
max_len: 100
}];
// Max 25 MB per FR-5.
bytes file_content = 5 [(buf.validate.field).bytes = {
min_len: 1
max_len: 26214400
}];
}

message UploadCostAttachmentResponse {
common.v1.BaseResponse base = 1;
CostAttachment data = 2;
}

message ListCostAttachmentsByRequestRequest {
int64 request_id = 1 [(buf.validate.field).int64.gte = 1];
}

message ListCostAttachmentsByRequestResponse {
common.v1.BaseResponse base = 1;
repeated CostAttachment data = 2;
}

message ListCostAttachmentsByCommentRequest {
int64 comment_id = 1 [(buf.validate.field).int64.gte = 1];
}

message ListCostAttachmentsByCommentResponse {
common.v1.BaseResponse base = 1;
repeated CostAttachment data = 2;
}

message GetCostAttachmentDownloadURLRequest {
int64 attachment_id = 1 [(buf.validate.field).int64.gte = 1];
}

message GetCostAttachmentDownloadURLResponse {
common.v1.BaseResponse base = 1;
string url = 2;
int32 valid_seconds = 3;
}

message DeleteCostAttachmentRequest {
int64 attachment_id = 1 [(buf.validate.field).int64.gte = 1];
}

message DeleteCostAttachmentResponse {
common.v1.BaseResponse base = 1;
}

service CostAttachmentService {
rpc UploadCostAttachment(UploadCostAttachmentRequest) returns (UploadCostAttachmentResponse) {
option (google.api.http) = {
post: "/api/v1/finance/cost-attachments/upload"
body: "*"
};
}
rpc ListCostAttachmentsByRequest(ListCostAttachmentsByRequestRequest) returns (ListCostAttachmentsByRequestResponse) {
option (google.api.http) = {get: "/api/v1/finance/cost-product-requests/{request_id}/attachments"};
}
rpc ListCostAttachmentsByComment(ListCostAttachmentsByCommentRequest) returns (ListCostAttachmentsByCommentResponse) {
option (google.api.http) = {get: "/api/v1/finance/cost-request-comments/{comment_id}/attachments"};
}
rpc GetCostAttachmentDownloadURL(GetCostAttachmentDownloadURLRequest) returns (GetCostAttachmentDownloadURLResponse) {
option (google.api.http) = {get: "/api/v1/finance/cost-attachments/{attachment_id}/download-url"};
}
rpc DeleteCostAttachment(DeleteCostAttachmentRequest) returns (DeleteCostAttachmentResponse) {
option (google.api.http) = {delete: "/api/v1/finance/cost-attachments/{attachment_id}"};
}
}
50 changes: 50 additions & 0 deletions finance/v1/cost_audit_log.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
syntax = "proto3";

package finance.v1;

import "buf/validate/validate.proto";
import "common/v1/common.proto";
import "google/api/annotations.proto";

// =============================================================================
// CostAuditLog — PRD Phase A §7.1.14 (CAL_).
// Append-only audit trail. Writes happen inside the business handlers (e.g.,
// CostProductRequestService.DecideFeasibility appends a CAL_ row). This service
// exposes READ-ONLY queries for admin viewing — there is no CreateAuditLog RPC.
// =============================================================================

message CostAuditLog {
int64 log_id = 1;
string entity_type = 2;
int64 entity_id = 3;
string operation = 4;
// before/after data as JSON-stringified objects.
string before_data = 5;
string after_data = 6;
string user_id = 7;
string performed_at = 8;
}

message ListCostAuditLogsRequest {
// Optional filters; all return everything when empty.
string entity_type = 1 [(buf.validate.field).string.max_len = 50];
int64 entity_id = 2;
string user_id = 3 [(buf.validate.field).string.max_len = 64];
string operation = 4 [(buf.validate.field).string.max_len = 30];
// ISO date YYYY-MM-DD inclusive.
string from_date = 5 [(buf.validate.field).string.max_len = 10];
string to_date = 6 [(buf.validate.field).string.max_len = 10];
common.v1.PaginationRequest pagination = 7;
}

message ListCostAuditLogsResponse {
common.v1.BaseResponse base = 1;
repeated CostAuditLog data = 2;
common.v1.PaginationResponse pagination = 3;
}

service CostAuditLogService {
rpc ListCostAuditLogs(ListCostAuditLogsRequest) returns (ListCostAuditLogsResponse) {
option (google.api.http) = {get: "/api/v1/finance/cost-audit-logs"};
}
}
Loading
Loading