Repository: ConduitIO/conduit-commons
Pull request #204: Added Metadata for chunked records
Author: login: parikshitg
Created: 2025-05-14T13:01:02Z | Merged: 2025-05-15T16:31:40Z

### Description

Added MetaData for chunked records.

### Quick checks:

- [x] I have followed the [Code Guidelines](https://github.com/ConduitIO/conduit/blob/main/docs/code_guidelines.md).
- [x] There is no other [pull request](https://github.com/ConduitIO/conduit-commons/pulls) for the same update/change.
- [ ] I have written unit tests.
- [x] I have made sure that the PR is of reasonable size and can be easily reviewed.



Diff:
diff --git a/.github/workflows/buf-validate.yaml b/.github/workflows/buf-validate.yaml
index 56b3361..405d7fc 100644
--- a/.github/workflows/buf-validate.yaml
+++ b/.github/workflows/buf-validate.yaml
@@ -20,7 +20,7 @@ jobs:
       - name: Get Buf version
         id: buf-version
         run: |
-          BUF_VERSION=$( go list -m -f '{{.Version}}' github.com/bufbuild/buf )
+          BUF_VERSION=$( go list -modfile=tools/go.mod -m -f '{{.Version}}' github.com/bufbuild/buf )
           # remove the leading 'v' in front of the version
           BUF_VERSION=${BUF_VERSION#v}
           echo "v=$BUF_VERSION" >> "$GITHUB_OUTPUT"
diff --git a/go.mod b/go.mod
index a560d85..32c0ada 100644
--- a/go.mod
+++ b/go.mod
@@ -16,7 +16,7 @@ require (
 	github.com/twmb/go-cache v1.2.1
 	go.uber.org/goleak v1.3.0
 	go.uber.org/mock v0.5.2
-	golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
+	golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6
 	google.golang.org/protobuf v1.36.6
 	modernc.org/sqlite v1.37.0
 )
@@ -29,6 +29,7 @@ require (
 	github.com/go-logr/logr v1.4.2 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
 	github.com/google/flatbuffers v25.2.10+incompatible // indirect
+	github.com/google/pprof v0.0.0-20250501235452-c0086092b71a // indirect
 	github.com/jackc/pgpassfile v1.0.0 // indirect
 	github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
 	github.com/jackc/puddle/v2 v2.2.2 // indirect
@@ -44,11 +45,11 @@ require (
 	go.opentelemetry.io/otel v1.35.0 // indirect
 	go.opentelemetry.io/otel/metric v1.35.0 // indirect
 	go.opentelemetry.io/otel/trace v1.35.0 // indirect
-	golang.org/x/crypto v0.36.0 // indirect
-	golang.org/x/net v0.38.0 // indirect
-	golang.org/x/sync v0.12.0 // indirect
-	golang.org/x/sys v0.31.0 // indirect
-	golang.org/x/text v0.23.0 // indirect
+	golang.org/x/crypto v0.38.0 // indirect
+	golang.org/x/net v0.40.0 // indirect
+	golang.org/x/sync v0.14.0 // indirect
+	golang.org/x/sys v0.33.0 // indirect
+	golang.org/x/text v0.25.0 // indirect
 	modernc.org/libc v1.62.1 // indirect
 	modernc.org/mathutil v1.7.1 // indirect
 	modernc.org/memory v1.9.1 // indirect
diff --git a/go.sum b/go.sum
index 27c9025..6a9dad5 100644
--- a/go.sum
+++ b/go.sum
@@ -26,8 +26,8 @@ github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZat
 github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
 github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
-github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
+github.com/google/pprof v0.0.0-20250501235452-c0086092b71a h1:rDA3FfmxwXR+BVKKdz55WwMJ1pD2hJQNW31d+l3mPk4=
+github.com/google/pprof v0.0.0-20250501235452-c0086092b71a/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/hamba/avro/v2 v2.28.0 h1:E8J5D27biyAulWKNiEBhV85QPc9xRMCUCGJewS0KYCE=
@@ -90,25 +90,25 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
 go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
 go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
 go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
-golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
-golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
-golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
-golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
+golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
+golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
+golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
+golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
 golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
 golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
-golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
-golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
-golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
-golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
+golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
+golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
+golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
-golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
-golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
-golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
-golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
-golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
+golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
+golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
+golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
+golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
+golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
 google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
 google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/opencdc/metadata.go b/opencdc/metadata.go
index f2686c6..3c691f7 100644
--- a/opencdc/metadata.go
+++ b/opencdc/metadata.go
@@ -58,6 +58,25 @@ const (
 	// the record's .Payload field.
 	MetadataPayloadSchemaVersion = "opencdc.payload.schema.version"
 
+	// MetadataFileName is a Record.Metadata key for the original file name,
+	// applicable when the record originates from a file-based source.
+	MetadataFileName = "opencdc.file.name"
+	// MetadataFileSize is a Record.Metadata key for the total size (in bytes)
+	// of the original file, if the record is derived from a file.
+	MetadataFileSize = "opencdc.file.size"
+	// MetadataFileHash is a Record.Metadata key for the hash (e.g., SHA-256) of
+	// the complete file, used when the record originates from a file.
+	MetadataFileHash = "opencdc.file.hash"
+	// MetadataFileChunked is a Record.Metadata key that indicates whether
+	// the record represents a chunk of a larger file (i.e., part of a chunked transfer).
+	MetadataFileChunked = "opencdc.file.chunked"
+	// MetadataFileChunkIndex is a Record.Metadata key for the one-based index
+	// of the current chunk, if the record is part of a chunked file.
+	MetadataFileChunkIndex = "opencdc.file.chunk.index"
+	// MetadataFileChunkCount is a Record.Metadata key indicating the total
+	// number of chunks the file was split into, when chunking is used.
+	MetadataFileChunkCount = "opencdc.file.chunk.count"
+
 	// MetadataConduitSourcePluginName is a Record.Metadata key for the name of
 	// the source plugin that created this record.
 	MetadataConduitSourcePluginName = "conduit.source.plugin.name"
@@ -313,6 +332,109 @@ func (m Metadata) SetPayloadSchemaVersion(version int) {
 	m[MetadataPayloadSchemaVersion] = strconv.Itoa(version)
 }
 
+// GetFileName gets the metadata value for key MetadataFileName.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileName() (string, error) {
+	return m.getValue(MetadataFileName)
+}
+
+// SetFileName sets the metadata value for key MetadataFileName.
+func (m Metadata) SetFileName(filename string) {
+	m[MetadataFileName] = filename
+}
+
+// GetFileSize gets the metadata value for key MetadataFileSize.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileSize() (int64, error) {
+	size, err := m.getValue(MetadataFileSize)
+	if err != nil {
+		return 0, err
+	}
+
+	filesize, err := strconv.ParseInt(size, 10, 64)
+	if err != nil {
+		return 0, fmt.Errorf("invalid filesize %q: %w", size, err)
+	}
+
+	return filesize, nil
+}
+
+// SetFileSize sets the metadata value for key MetadataFileSize.
+func (m Metadata) SetFileSize(filesize int64) {
+	m[MetadataFileSize] = strconv.FormatInt(filesize, 10)
+}
+
+// GetFileHash gets the metadata value for key MetadataFileHash.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileHash() (string, error) {
+	return m.getValue(MetadataFileHash)
+}
+
+// SetFileHash sets the metadata value for key MetadataFileHash.
+func (m Metadata) SetFileHash(filehash string) {
+	m[MetadataFileHash] = filehash
+}
+
+// GetFileChunked gets the metadata value for key MetadataFileChunked.
+func (m Metadata) GetFileChunked() (bool, error) {
+	val, err := m.getValue(MetadataFileChunked)
+	if err != nil {
+		return false, err
+	}
+	chunked, err := strconv.ParseBool(val)
+	if err != nil {
+		return false, fmt.Errorf("error parsing bool value %q: %w", val, err)
+	}
+	return chunked, nil
+}
+
+// SetFileChunked sets the metadata value for key MetadataFileChunked.
+func (m Metadata) SetFileChunked(ok bool) {
+	m[MetadataFileChunked] = strconv.FormatBool(ok)
+}
+
+// GetFileChunkIndex gets the metadata value for key MetadataFileChunkIndex.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileChunkIndex() (int, error) {
+	i, err := m.getValue(MetadataFileChunkIndex)
+	if err != nil {
+		return 0, err
+	}
+
+	filesize, err := strconv.Atoi(i)
+	if err != nil {
+		return 0, fmt.Errorf("invalid chunk index %q: %w", i, err)
+	}
+
+	return filesize, nil
+}
+
+// SetFileChunkIndex sets the metadata value for key MetadataFileChunkIndex.
+func (m Metadata) SetFileChunkIndex(i int) {
+	m[MetadataFileChunkIndex] = strconv.Itoa(i)
+}
+
+// GetFileChunkCount gets the metadata value for key MetadataFileChunkCount.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileChunkCount() (int, error) {
+	i, err := m.getValue(MetadataFileChunkCount)
+	if err != nil {
+		return 0, err
+	}
+
+	filesize, err := strconv.Atoi(i)
+	if err != nil {
+		return 0, fmt.Errorf("invalid chunk total %q: %w", i, err)
+	}
+
+	return filesize, nil
+}
+
+// SetFileChunkCount sets the metadata value for key MetadataFileChunkCount.
+func (m Metadata) SetFileChunkCount(i int) {
+	m[MetadataFileChunkCount] = strconv.Itoa(i)
+}
+
 // getValue returns the value for a specific key. If the value does not exist or
 // is empty the function returns ErrMetadataFieldNotFound.
 func (m Metadata) getValue(key string) (string, error) {
diff --git a/proto/config/v1/parameter.proto b/proto/config/v1/parameter.proto
index 2d292f3..2806726 100644
--- a/proto/config/v1/parameter.proto
+++ b/proto/config/v1/parameter.proto
@@ -56,4 +56,4 @@ message Validation {
   // The value to be compared with the parameter,
   // or a comma separated list in case of Validation.TYPE_INCLUSION or Validation.TYPE_EXCLUSION.
   string value = 2;
-}
\ No newline at end of file
+}
diff --git a/proto/metadata/v1/constants.proto b/proto/metadata/v1/constants.proto
index e1a8196..0d6a3b9 100644
--- a/proto/metadata/v1/constants.proto
+++ b/proto/metadata/v1/constants.proto
@@ -5,15 +5,13 @@ package metadata.v1;
 import "google/protobuf/descriptor.proto";
 
 option go_package = "github.com/conduitio/conduit-commons/proto/metadata/v1";
-
-option (metadata_conduit_source_plugin_name) = "conduit.source.plugin.name";
-option (metadata_conduit_source_plugin_version) = "conduit.source.plugin.version";
 option (metadata_conduit_destination_plugin_name) = "conduit.destination.plugin.name";
 option (metadata_conduit_destination_plugin_version) = "conduit.destination.plugin.version";
-
-option(metadata_conduit_source_connector_id) = "conduit.source.connector.id";
-option(metadata_conduit_dlq_nack_error) = "conduit.dlq.nack.error";
-option(metadata_conduit_dlq_nack_node_id) = "conduit.dlq.nack.node.id";
+option (metadata_conduit_dlq_nack_error) = "conduit.dlq.nack.error";
+option (metadata_conduit_dlq_nack_node_id) = "conduit.dlq.nack.node.id";
+option (metadata_conduit_source_connector_id) = "conduit.source.connector.id";
+option (metadata_conduit_source_plugin_name) = "conduit.source.plugin.name";
+option (metadata_conduit_source_plugin_version) = "conduit.source.plugin.version";
 
 // We are (ab)using custom file options to define constants.
 // See https://github.com/protocolbuffers/protobuf/issues/3520#issuecomment-323613839
diff --git a/proto/opencdc/v1/opencdc.pb.go b/proto/opencdc/v1/opencdc.pb.go
index 3e1cd70..184e503 100644
--- a/proto/opencdc/v1/opencdc.pb.go
+++ b/proto/opencdc/v1/opencdc.pb.go
@@ -395,6 +395,54 @@ var file_opencdc_v1_opencdc_proto_extTypes = []protoimpl.ExtensionInfo{
 		Tag:           "bytes,10007,opt,name=metadata_payload_schema_version",
 		Filename:      "opencdc/v1/opencdc.proto",
 	},
+	{
+		ExtendedType:  (*descriptorpb.FileOptions)(nil),
+		ExtensionType: (*string)(nil),
+		Field:         10008,
+		Name:          "opencdc.v1.metadata_file_name",
+		Tag:           "bytes,10008,opt,name=metadata_file_name",
+		Filename:      "opencdc/v1/opencdc.proto",
+	},
+	{
+		ExtendedType:  (*descriptorpb.FileOptions)(nil),
+		ExtensionType: (*int64)(nil),
+		Field:         10009,
+		Name:          "opencdc.v1.metadata_file_size",
+		Tag:           "varint,10009,opt,name=metadata_file_size",
+		Filename:      "opencdc/v1/opencdc.proto",
+	},
+	{
+		ExtendedType:  (*descriptorpb.FileOptions)(nil),
+		ExtensionType: (*string)(nil),
+		Field:         10010,
+		Name:          "opencdc.v1.metadata_file_hash",
+		Tag:           "bytes,10010,opt,name=metadata_file_hash",
+		Filename:      "opencdc/v1/opencdc.proto",
+	},
+	{
+		ExtendedType:  (*descriptorpb.FileOptions)(nil),
+		ExtensionType: (*bool)(nil),
+		Field:         10011,
+		Name:          "opencdc.v1.metadata_file_chunked",
+		Tag:           "varint,10011,opt,name=metadata_file_chunked",
+		Filename:      "opencdc/v1/opencdc.proto",
+	},
+	{
+		ExtendedType:  (*descriptorpb.FileOptions)(nil),
+		ExtensionType: (*int64)(nil),
+		Field:         10012,
+		Name:          "opencdc.v1.metadata_file_chunk_index",
+		Tag:           "varint,10012,opt,name=metadata_file_chunk_index",
+		Filename:      "opencdc/v1/opencdc.proto",
+	},
+	{
+		ExtendedType:  (*descriptorpb.FileOptions)(nil),
+		ExtensionType: (*int64)(nil),
+		Field:         10013,
+		Name:          "opencdc.v1.metadata_file_chunk_count",
+		Tag:           "varint,10013,opt,name=metadata_file_chunk_count",
+		Filename:      "opencdc/v1/opencdc.proto",
+	},
 }
 
 // Extension fields to descriptorpb.FileOptions.
@@ -450,6 +498,30 @@ var (
 	//
 	// optional string metadata_payload_schema_version = 10007;
 	E_MetadataPayloadSchemaVersion = &file_opencdc_v1_opencdc_proto_extTypes[8]
+	// Metadata field "opencdc.file.name" contains the file name of the file record.
+	//
+	// optional string metadata_file_name = 10008;
+	E_MetadataFileName = &file_opencdc_v1_opencdc_proto_extTypes[9]
+	// Metadata field "opencdc.file.size" contains the file size of the file record.
+	//
+	// optional int64 metadata_file_size = 10009;
+	E_MetadataFileSize = &file_opencdc_v1_opencdc_proto_extTypes[10]
+	// Metadata field "opencdc.file.hash" contains the file content hash of the file record.
+	//
+	// optional string metadata_file_hash = 10010;
+	E_MetadataFileHash = &file_opencdc_v1_opencdc_proto_extTypes[11]
+	// Metadata field "opencdc.file.chunked" contains if the record is chunked record of a file.
+	//
+	// optional bool metadata_file_chunked = 10011;
+	E_MetadataFileChunked = &file_opencdc_v1_opencdc_proto_extTypes[12]
+	// Metadata field "opencdc.file.chunk.index" contains the chunk index of the file record.
+	//
+	// optional int64 metadata_file_chunk_index = 10012;
+	E_MetadataFileChunkIndex = &file_opencdc_v1_opencdc_proto_extTypes[13]
+	// Metadata field "opencdc.file.chunk.count" contains the total number of chunks of the file record.
+	//
+	// optional int64 metadata_file_chunk_count = 10013;
+	E_MetadataFileChunkCount = &file_opencdc_v1_opencdc_proto_extTypes[14]
 )
 
 var File_opencdc_v1_opencdc_proto protoreflect.FileDescriptor
@@ -549,31 +621,62 @@ var file_opencdc_v1_opencdc_proto_rawDesc = []byte{
 	0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x97, 0x4e, 0x20,
 	0x01, 0x28, 0x09, 0x52, 0x1c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x50, 0x61, 0x79,
 	0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
-	0x6e, 0x42, 0xfe, 0x02, 0xfa, 0xf0, 0x04, 0x02, 0x76, 0x31, 0x82, 0xf1, 0x04, 0x0f, 0x6f, 0x70,
-	0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x8a, 0xf1, 0x04,
-	0x11, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
-	0x41, 0x74, 0x92, 0xf1, 0x04, 0x0e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x72, 0x65,
-	0x61, 0x64, 0x41, 0x74, 0x9a, 0xf1, 0x04, 0x12, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e,
-	0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0xa2, 0xf1, 0x04, 0x1a, 0x6f, 0x70,
-	0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x6b, 0x65, 0x79, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
-	0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0xaa, 0xf1, 0x04, 0x1a, 0x6f, 0x70, 0x65, 0x6e,
-	0x63, 0x64, 0x63, 0x2e, 0x6b, 0x65, 0x79, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x76,
-	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0xb2, 0xf1, 0x04, 0x1e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64,
+	0x6e, 0x3a, 0x4b, 0x0a, 0x12, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x66, 0x69,
+	0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70,
+	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x98, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6d, 0x65,
+	0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x4b,
+	0x0a, 0x12, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f,
+	0x73, 0x69, 0x7a, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+	0x6e, 0x73, 0x18, 0x99, 0x4e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6d, 0x65, 0x74, 0x61, 0x64,
+	0x61, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x3a, 0x4b, 0x0a, 0x12, 0x6d,
+	0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x68, 0x61, 0x73,
+	0x68, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
+	0x9a, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+	0x46, 0x69, 0x6c, 0x65, 0x48, 0x61, 0x73, 0x68, 0x3a, 0x51, 0x0a, 0x15, 0x6d, 0x65, 0x74, 0x61,
+	0x64, 0x61, 0x74, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x65,
+	0x64, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
+	0x9b, 0x4e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+	0x46, 0x69, 0x6c, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x65, 0x64, 0x3a, 0x58, 0x0a, 0x19, 0x6d,
+	0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x68, 0x75,
+	0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f,
+	0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9c, 0x4e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6d,
+	0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b,
+	0x49, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x58, 0x0a, 0x19, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+	0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x5f, 0x63, 0x6f, 0x75,
+	0x6e, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+	0x18, 0x9d, 0x4e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+	0x61, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x42,
+	0xfe, 0x02, 0xfa, 0xf0, 0x04, 0x02, 0x76, 0x31, 0x82, 0xf1, 0x04, 0x0f, 0x6f, 0x70, 0x65, 0x6e,
+	0x63, 0x64, 0x63, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x8a, 0xf1, 0x04, 0x11, 0x6f,
+	0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
+	0x92, 0xf1, 0x04, 0x0e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x72, 0x65, 0x61, 0x64,
+	0x41, 0x74, 0x9a, 0xf1, 0x04, 0x12, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x63, 0x6f,
+	0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0xa2, 0xf1, 0x04, 0x1a, 0x6f, 0x70, 0x65, 0x6e,
+	0x63, 0x64, 0x63, 0x2e, 0x6b, 0x65, 0x79, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x73,
+	0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0xaa, 0xf1, 0x04, 0x1a, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64,
+	0x63, 0x2e, 0x6b, 0x65, 0x79, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x76, 0x65, 0x72,
+	0x73, 0x69, 0x6f, 0x6e, 0xb2, 0xf1, 0x04, 0x1e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e,
+	0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x73,
+	0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0xba, 0xf1, 0x04, 0x1e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64,
 	0x63, 0x2e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
-	0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0xba, 0xf1, 0x04, 0x1e, 0x6f, 0x70, 0x65, 0x6e,
-	0x63, 0x64, 0x63, 0x2e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x73, 0x63, 0x68, 0x65,
-	0x6d, 0x61, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e,
-	0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x4f, 0x70, 0x65, 0x6e,
-	0x63, 0x64, 0x63, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68,
-	0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x64, 0x75, 0x69, 0x74, 0x69, 0x6f,
-	0x2f, 0x63, 0x6f, 0x6e, 0x64, 0x75, 0x69, 0x74, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x73,
-	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2f, 0x76,
-	0x31, 0x3b, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4f, 0x58,
-	0x58, 0xaa, 0x02, 0x0a, 0x4f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x56, 0x31, 0xca, 0x02,
-	0x0a, 0x4f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x16, 0x4f, 0x70,
-	0x65, 0x6e, 0x63, 0x64, 0x63, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61,
-	0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x3a, 0x3a,
-	0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x70,
+	0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x4f, 0x70, 0x65, 0x6e, 0x63, 0x64,
+	0x63, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
+	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x64, 0x75, 0x69, 0x74, 0x69, 0x6f, 0x2f, 0x63,
+	0x6f, 0x6e, 0x64, 0x75, 0x69, 0x74, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x73, 0x2f, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2f, 0x76, 0x31, 0x3b,
+	0x6f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4f, 0x58, 0x58, 0xaa,
+	0x02, 0x0a, 0x4f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0a, 0x4f,
+	0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x16, 0x4f, 0x70, 0x65, 0x6e,
+	0x63, 0x64, 0x63, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+	0x74, 0x61, 0xea, 0x02, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x63, 0x64, 0x63, 0x3a, 0x3a, 0x56, 0x31,
+	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -616,10 +719,16 @@ var file_opencdc_v1_opencdc_proto_depIdxs = []int32{
 	6,  // 13: opencdc.v1.metadata_key_schema_version:extendee -> google.protobuf.FileOptions
 	6,  // 14: opencdc.v1.metadata_payload_schema_subject:extendee -> google.protobuf.FileOptions
 	6,  // 15: opencdc.v1.metadata_payload_schema_version:extendee -> google.protobuf.FileOptions
-	16, // [16:16] is the sub-list for method output_type
-	16, // [16:16] is the sub-list for method input_type
-	16, // [16:16] is the sub-list for extension type_name
-	7,  // [7:16] is the sub-list for extension extendee
+	6,  // 16: opencdc.v1.metadata_file_name:extendee -> google.protobuf.FileOptions
+	6,  // 17: opencdc.v1.metadata_file_size:extendee -> google.protobuf.FileOptions
+	6,  // 18: opencdc.v1.metadata_file_hash:extendee -> google.protobuf.FileOptions
+	6,  // 19: opencdc.v1.metadata_file_chunked:extendee -> google.protobuf.FileOptions
+	6,  // 20: opencdc.v1.metadata_file_chunk_index:extendee -> google.protobuf.FileOptions
+	6,  // 21: opencdc.v1.metadata_file_chunk_count:extendee -> google.protobuf.FileOptions
+	22, // [22:22] is the sub-list for method output_type
+	22, // [22:22] is the sub-list for method input_type
+	22, // [22:22] is the sub-list for extension type_name
+	7,  // [7:22] is the sub-list for extension extendee
 	0,  // [0:7] is the sub-list for field type_name
 }
 
@@ -677,7 +786,7 @@ func file_opencdc_v1_opencdc_proto_init() {
 			RawDescriptor: file_opencdc_v1_opencdc_proto_rawDesc,
 			NumEnums:      1,
 			NumMessages:   4,
-			NumExtensions: 9,
+			NumExtensions: 15,
 			NumServices:   0,
 		},
 		GoTypes:           file_opencdc_v1_opencdc_proto_goTypes,
diff --git a/proto/opencdc/v1/opencdc.proto b/proto/opencdc/v1/opencdc.proto
index 1862505..a0a8520 100644
--- a/proto/opencdc/v1/opencdc.proto
+++ b/proto/opencdc/v1/opencdc.proto
@@ -6,17 +6,15 @@ import "google/protobuf/descriptor.proto";
 import "google/protobuf/struct.proto";
 
 option go_package = "github.com/conduitio/conduit-commons/proto/opencdc/v1";
-
-option (opencdc_version) = "v1";
-
-option (metadata_created_at) = "opencdc.createdAt";
-option (metadata_read_at) = "opencdc.readAt";
-option (metadata_version) = "opencdc.version";
 option (metadata_collection) = "opencdc.collection";
+option (metadata_created_at) = "opencdc.createdAt";
 option (metadata_key_schema_subject) = "opencdc.key.schema.subject";
 option (metadata_key_schema_version) = "opencdc.key.schema.version";
 option (metadata_payload_schema_subject) = "opencdc.payload.schema.subject";
 option (metadata_payload_schema_version) = "opencdc.payload.schema.version";
+option (metadata_read_at) = "opencdc.readAt";
+option (metadata_version) = "opencdc.version";
+option (opencdc_version) = "v1";
 
 // We are (ab)using custom file options to define constants.
 // See https://github.com/protocolbuffers/protobuf/issues/3520#issuecomment-323613839
@@ -55,6 +53,19 @@ extend google.protobuf.FileOptions {
   // Metadata field "opencdc.payload.schema.version" contains the version of the schema of
   // the record's .Payload fields.
   string metadata_payload_schema_version = 10007;
+
+  // Metadata field "opencdc.file.name" contains the file name of the file record.
+  string metadata_file_name = 10008;
+  // Metadata field "opencdc.file.size" contains the file size of the file record.
+  int64 metadata_file_size = 10009;
+  // Metadata field "opencdc.file.hash" contains the file content hash of the file record.
+  string metadata_file_hash = 10010;
+  // Metadata field "opencdc.file.chunked" contains if the record is chunked record of a file.
+  bool metadata_file_chunked = 10011;
+  // Metadata field "opencdc.file.chunk.index" contains the chunk index of the file record.
+  int64 metadata_file_chunk_index = 10012;
+  // Metadata field "opencdc.file.chunk.count" contains the total number of chunks of the file record.
+  int64 metadata_file_chunk_count = 10013;
 }
 
 // Operation defines what triggered the creation of a record.


Reviews:
user: login: grvsahil
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T08:46:30Z
user: login: hariso
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T12:44:44Z
user: login: hariso
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T12:45:13Z
user: login: hariso
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T12:47:32Z
user: login: hariso
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T12:50:18Z
user: login: grvsahil
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T12:53:15Z
user: login: grvsahil
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T12:55:23Z
user: login: parikshitg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T13:06:58Z
user: login: parikshitg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T13:15:41Z
user: login: hariso
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T14:38:20Z

Review comments:
diff_hunk: @@ -5,15 +5,13 @@ package metadata.v1;
 import "google/protobuf/descriptor.proto";
 
 option go_package = "github.com/conduitio/conduit-commons/proto/metadata/v1";
-
-option (metadata_conduit_source_plugin_name) = "conduit.source.plugin.name";
-option (metadata_conduit_source_plugin_version) = "conduit.source.plugin.version";
 option (metadata_conduit_destination_plugin_name) = "conduit.destination.plugin.name";
 option (metadata_conduit_destination_plugin_version) = "conduit.destination.plugin.version";
-
-option(metadata_conduit_source_connector_id) = "conduit.source.connector.id";
-option(metadata_conduit_dlq_nack_error) = "conduit.dlq.nack.error";
-option(metadata_conduit_dlq_nack_node_id) = "conduit.dlq.nack.node.id";
+option (metadata_conduit_dlq_nack_error) = "conduit.dlq.nack.error";
+option (metadata_conduit_dlq_nack_node_id) = "conduit.dlq.nack.node.id";
+option (metadata_conduit_source_connector_id) = "conduit.source.connector.id";
+option (metadata_conduit_source_plugin_name) = "conduit.source.plugin.name";
+option (metadata_conduit_source_plugin_version) = "conduit.source.plugin.version";
path: proto/metadata/v1/constants.proto
user: login: hariso
body: Hmm, why did these lines get changed?
created_at: 2025-05-15T12:44:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -6,17 +6,15 @@ import "google/protobuf/descriptor.proto";
 import "google/protobuf/struct.proto";
 
 option go_package = "github.com/conduitio/conduit-commons/proto/opencdc/v1";
-
-option (opencdc_version) = "v1";
-
-option (metadata_created_at) = "opencdc.createdAt";
-option (metadata_read_at) = "opencdc.readAt";
-option (metadata_version) = "opencdc.version";
 option (metadata_collection) = "opencdc.collection";
+option (metadata_created_at) = "opencdc.createdAt";
 option (metadata_key_schema_subject) = "opencdc.key.schema.subject";
 option (metadata_key_schema_version) = "opencdc.key.schema.version";
 option (metadata_payload_schema_subject) = "opencdc.payload.schema.subject";
 option (metadata_payload_schema_version) = "opencdc.payload.schema.version";
+option (metadata_read_at) = "opencdc.readAt";
+option (metadata_version) = "opencdc.version";
+option (opencdc_version) = "v1";
path: proto/opencdc/v1/opencdc.proto
user: login: hariso
body: It looks like Buf re-ordered these or ?
created_at: 2025-05-15T12:45:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -313,6 +332,112 @@ func (m Metadata) SetPayloadSchemaVersion(version int) {
 	m[MetadataPayloadSchemaVersion] = strconv.Itoa(version)
 }
 
+// GetFileName gets the metadata value for key MetadataFileName.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileName() (string, error) {
+	return m.getValue(MetadataFileName)
+}
+
+// SetFileName sets the metadata value for key MetadataFileName.
+func (m Metadata) SetFileName(filename string) {
+	m[MetadataFileName] = filename
+}
+
+// GetFileSize gets the metadata value for key MetadataFileSize.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileSize() (int64, error) {
+	size, err := m.getValue(MetadataFileSize)
+	if err != nil {
+		return 0, err
+	}
+
+	filesize, err := strconv.ParseInt(size, 10, 64)
+	if err != nil {
+		return 0, fmt.Errorf("invalid filesize %q: %w", size, err)
+	}
+
+	return filesize, nil
+}
+
+// SetFileSize sets the metadata value for key MetadataFileSize.
+func (m Metadata) SetFileSize(filesize int64) {
+	m[MetadataFileSize] = strconv.FormatInt(filesize, 10)
+}
+
+// GetFileHash gets the metadata value for key MetadataFileHash.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileHash() (string, error) {
+	return m.getValue(MetadataFileHash)
+}
+
+// SetFileHash sets the metadata value for key MetadataFileHash.
+func (m Metadata) SetFileHash(filehash string) {
+	m[MetadataFileHash] = filehash
+}
+
+// GetFileIsChunked gets the metadata value for key MetadataFileHash.
+func (m Metadata) GetFileChunked() bool {
+	chunked, err := m.getValue(MetadataFileChunked)
+	if err != nil {
+		return false
+	}
+	if chunked == "true" {
+		return true
+	}
+	return false
+}
+
+// SetFileIsChunked sets the metadata value for key MetadataFileHash.
+func (m Metadata) SetFileChunked(ok bool) {
+	if ok {
+		m[MetadataFileChunked] = "true"
+	} else {
+		m[MetadataFileChunked] = "false"
+	}
path: opencdc/metadata.go
user: login: hariso
body: Nitpick: can be simplified with `strconv.FormatBool`.
created_at: 2025-05-15T12:47:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -313,6 +332,112 @@ func (m Metadata) SetPayloadSchemaVersion(version int) {
 	m[MetadataPayloadSchemaVersion] = strconv.Itoa(version)
 }
 
+// GetFileName gets the metadata value for key MetadataFileName.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileName() (string, error) {
+	return m.getValue(MetadataFileName)
+}
+
+// SetFileName sets the metadata value for key MetadataFileName.
+func (m Metadata) SetFileName(filename string) {
+	m[MetadataFileName] = filename
+}
+
+// GetFileSize gets the metadata value for key MetadataFileSize.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileSize() (int64, error) {
+	size, err := m.getValue(MetadataFileSize)
+	if err != nil {
+		return 0, err
+	}
+
+	filesize, err := strconv.ParseInt(size, 10, 64)
+	if err != nil {
+		return 0, fmt.Errorf("invalid filesize %q: %w", size, err)
+	}
+
+	return filesize, nil
+}
+
+// SetFileSize sets the metadata value for key MetadataFileSize.
+func (m Metadata) SetFileSize(filesize int64) {
+	m[MetadataFileSize] = strconv.FormatInt(filesize, 10)
+}
+
+// GetFileHash gets the metadata value for key MetadataFileHash.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileHash() (string, error) {
+	return m.getValue(MetadataFileHash)
+}
+
+// SetFileHash sets the metadata value for key MetadataFileHash.
+func (m Metadata) SetFileHash(filehash string) {
+	m[MetadataFileHash] = filehash
+}
+
+// GetFileIsChunked gets the metadata value for key MetadataFileHash.
+func (m Metadata) GetFileChunked() bool {
+	chunked, err := m.getValue(MetadataFileChunked)
+	if err != nil {
+		return false
+	}
+	if chunked == "true" {
+		return true
+	}
+	return false
path: opencdc/metadata.go
user: login: hariso
body: I'd like to suggest to follow a similar approach as other methods, where we return an error, if we can't get the value. We can also use ``strconv.ParseBool` (it handles all the different letter case, and also handles 0, 1, t, f, etc.)
created_at: 2025-05-15T12:50:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -5,15 +5,13 @@ package metadata.v1;
 import "google/protobuf/descriptor.proto";
 
 option go_package = "github.com/conduitio/conduit-commons/proto/metadata/v1";
-
-option (metadata_conduit_source_plugin_name) = "conduit.source.plugin.name";
-option (metadata_conduit_source_plugin_version) = "conduit.source.plugin.version";
 option (metadata_conduit_destination_plugin_name) = "conduit.destination.plugin.name";
 option (metadata_conduit_destination_plugin_version) = "conduit.destination.plugin.version";
-
-option(metadata_conduit_source_connector_id) = "conduit.source.connector.id";
-option(metadata_conduit_dlq_nack_error) = "conduit.dlq.nack.error";
-option(metadata_conduit_dlq_nack_node_id) = "conduit.dlq.nack.node.id";
+option (metadata_conduit_dlq_nack_error) = "conduit.dlq.nack.error";
+option (metadata_conduit_dlq_nack_node_id) = "conduit.dlq.nack.node.id";
+option (metadata_conduit_source_connector_id) = "conduit.source.connector.id";
+option (metadata_conduit_source_plugin_name) = "conduit.source.plugin.name";
+option (metadata_conduit_source_plugin_version) = "conduit.source.plugin.version";
path: proto/metadata/v1/constants.proto
user: login: grvsahil
body: buf validate workflow was failing due to format issues, so I did `buf format` and these changes occurred.
created_at: 2025-05-15T12:53:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -6,17 +6,15 @@ import "google/protobuf/descriptor.proto";
 import "google/protobuf/struct.proto";
 
 option go_package = "github.com/conduitio/conduit-commons/proto/opencdc/v1";
-
-option (opencdc_version) = "v1";
-
-option (metadata_created_at) = "opencdc.createdAt";
-option (metadata_read_at) = "opencdc.readAt";
-option (metadata_version) = "opencdc.version";
 option (metadata_collection) = "opencdc.collection";
+option (metadata_created_at) = "opencdc.createdAt";
 option (metadata_key_schema_subject) = "opencdc.key.schema.subject";
 option (metadata_key_schema_version) = "opencdc.key.schema.version";
 option (metadata_payload_schema_subject) = "opencdc.payload.schema.subject";
 option (metadata_payload_schema_version) = "opencdc.payload.schema.version";
+option (metadata_read_at) = "opencdc.readAt";
+option (metadata_version) = "opencdc.version";
+option (opencdc_version) = "v1";
path: proto/opencdc/v1/opencdc.proto
user: login: grvsahil
body: Yes, did `buf format -w proto/` to make formatting changes for buf validate workflow.
created_at: 2025-05-15T12:55:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -313,6 +332,112 @@ func (m Metadata) SetPayloadSchemaVersion(version int) {
 	m[MetadataPayloadSchemaVersion] = strconv.Itoa(version)
 }
 
+// GetFileName gets the metadata value for key MetadataFileName.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileName() (string, error) {
+	return m.getValue(MetadataFileName)
+}
+
+// SetFileName sets the metadata value for key MetadataFileName.
+func (m Metadata) SetFileName(filename string) {
+	m[MetadataFileName] = filename
+}
+
+// GetFileSize gets the metadata value for key MetadataFileSize.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileSize() (int64, error) {
+	size, err := m.getValue(MetadataFileSize)
+	if err != nil {
+		return 0, err
+	}
+
+	filesize, err := strconv.ParseInt(size, 10, 64)
+	if err != nil {
+		return 0, fmt.Errorf("invalid filesize %q: %w", size, err)
+	}
+
+	return filesize, nil
+}
+
+// SetFileSize sets the metadata value for key MetadataFileSize.
+func (m Metadata) SetFileSize(filesize int64) {
+	m[MetadataFileSize] = strconv.FormatInt(filesize, 10)
+}
+
+// GetFileHash gets the metadata value for key MetadataFileHash.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileHash() (string, error) {
+	return m.getValue(MetadataFileHash)
+}
+
+// SetFileHash sets the metadata value for key MetadataFileHash.
+func (m Metadata) SetFileHash(filehash string) {
+	m[MetadataFileHash] = filehash
+}
+
+// GetFileIsChunked gets the metadata value for key MetadataFileHash.
+func (m Metadata) GetFileChunked() bool {
+	chunked, err := m.getValue(MetadataFileChunked)
+	if err != nil {
+		return false
+	}
+	if chunked == "true" {
+		return true
+	}
+	return false
+}
+
+// SetFileIsChunked sets the metadata value for key MetadataFileHash.
+func (m Metadata) SetFileChunked(ok bool) {
+	if ok {
+		m[MetadataFileChunked] = "true"
+	} else {
+		m[MetadataFileChunked] = "false"
+	}
path: opencdc/metadata.go
user: login: parikshitg
body: updated Thanks!
created_at: 2025-05-15T13:06:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -313,6 +332,112 @@ func (m Metadata) SetPayloadSchemaVersion(version int) {
 	m[MetadataPayloadSchemaVersion] = strconv.Itoa(version)
 }
 
+// GetFileName gets the metadata value for key MetadataFileName.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileName() (string, error) {
+	return m.getValue(MetadataFileName)
+}
+
+// SetFileName sets the metadata value for key MetadataFileName.
+func (m Metadata) SetFileName(filename string) {
+	m[MetadataFileName] = filename
+}
+
+// GetFileSize gets the metadata value for key MetadataFileSize.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileSize() (int64, error) {
+	size, err := m.getValue(MetadataFileSize)
+	if err != nil {
+		return 0, err
+	}
+
+	filesize, err := strconv.ParseInt(size, 10, 64)
+	if err != nil {
+		return 0, fmt.Errorf("invalid filesize %q: %w", size, err)
+	}
+
+	return filesize, nil
+}
+
+// SetFileSize sets the metadata value for key MetadataFileSize.
+func (m Metadata) SetFileSize(filesize int64) {
+	m[MetadataFileSize] = strconv.FormatInt(filesize, 10)
+}
+
+// GetFileHash gets the metadata value for key MetadataFileHash.
+// If the value does not exist or is empty the function returns ErrMetadataFieldNotFound.
+func (m Metadata) GetFileHash() (string, error) {
+	return m.getValue(MetadataFileHash)
+}
+
+// SetFileHash sets the metadata value for key MetadataFileHash.
+func (m Metadata) SetFileHash(filehash string) {
+	m[MetadataFileHash] = filehash
+}
+
+// GetFileIsChunked gets the metadata value for key MetadataFileHash.
+func (m Metadata) GetFileChunked() bool {
+	chunked, err := m.getValue(MetadataFileChunked)
+	if err != nil {
+		return false
+	}
+	if chunked == "true" {
+		return true
+	}
+	return false
path: opencdc/metadata.go
user: login: parikshitg
body: updated.
created_at: 2025-05-15T13:15:40Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-15T10:27:00Z
body: The latest Buf updates on your PR. Results from workflow <a href="https://github.com/ConduitIO/conduit-commons/actions/runs/15045818209">buf-validate / validate (pull_request)</a>.

<table><tr><th>Build</th><th>Format</th><th>Lint</th><th>Breaking</th><th>Updated (UTC)</th></tr><tr><td><code>✅ passed</code></td><td><code>✅ passed</code></td><td><code>✅ passed</code></td><td><code>✅ passed</code></td><td>May 15, 2025, 1:09 PM</td></tr></table>
<!-- buf buf-validate:validate -->
author_association: NONE
user: login: parikshitg
created_at: 2025-05-15T15:08:32Z
body: Hi @hariso, thanks for your review, we would need to create a tag for this repo for us to use these metadata. 
author_association: CONTRIBUTOR
user: login: hariso
created_at: 2025-05-15T16:34:05Z
body: > Hi @hariso, thanks for your review, we would need to create a tag for this repo for us to use these metadata.

Thank you for the pull request! I've just created the tag.
author_association: CONTRIBUTOR