Skip to content

Commit cd69adb

Browse files
authored
fix: remove captured_at from AI agent config material (#2917)
Signed-off-by: Jose I. Paris <jiparis@chainloop.dev>
1 parent 18d5096 commit cd69adb

14 files changed

Lines changed: 13 additions & 50 deletions

internal/aiagentconfig/aiagentconfig.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ type MCPServer struct {
7474
type Data struct {
7575
Agent Agent `json:"agent"`
7676
ConfigHash string `json:"config_hash"`
77-
CapturedAt string `json:"captured_at"`
7877
GitContext *GitContext `json:"git_context,omitempty"`
7978
ConfigFiles []ConfigFile `json:"config_files"`
8079
// Future fields for richer analysis

internal/aiagentconfig/builder.go

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"path/filepath"
2525
"sort"
2626
"strings"
27-
"time"
2827

2928
"github.com/rs/zerolog/log"
3029
)
@@ -33,12 +32,7 @@ import (
3332
// basePath is the base directory, discovered contains files relative to basePath with their kinds.
3433
// agentName identifies the AI agent (e.g. "claude", "cursor").
3534
// gitCtx may be nil if not in a git repository.
36-
// capturedAt is the timestamp to record in the output; pass time.Time{} to use the current time.
37-
func Build(basePath string, discovered []DiscoveredFile, agentName string, gitCtx *GitContext, capturedAt time.Time) (*Data, error) {
38-
if capturedAt.IsZero() {
39-
capturedAt = time.Now().UTC()
40-
}
41-
35+
func Build(basePath string, discovered []DiscoveredFile, agentName string, gitCtx *GitContext) (*Data, error) {
4236
// Resolve basePath to its real path so symlink comparisons are reliable
4337
realRoot, err := filepath.EvalSymlinks(basePath)
4438
if err != nil {
@@ -54,16 +48,11 @@ func Build(basePath string, discovered []DiscoveredFile, agentName string, gitCt
5448
relPath := df.Path
5549
absPath := filepath.Join(basePath, relPath)
5650

57-
content, realPath, err := safeReadFile(absPath, realRoot)
51+
content, _, err := safeReadFile(absPath, realRoot)
5852
if err != nil {
5953
return nil, fmt.Errorf("%s: %w", relPath, err)
6054
}
6155

62-
info, err := os.Stat(realPath)
63-
if err != nil {
64-
return nil, fmt.Errorf("stat %s: %w", relPath, err)
65-
}
66-
6756
hash := sha256.Sum256(content)
6857
hexHash := hex.EncodeToString(hash[:])
6958
hashes = append(hashes, fmt.Sprintf("%s:%s", relPath, hexHash))
@@ -72,7 +61,7 @@ func Build(basePath string, discovered []DiscoveredFile, agentName string, gitCt
7261
Path: relPath,
7362
Kind: df.Kind,
7463
SHA256: hexHash,
75-
Size: info.Size(),
64+
Size: int64(len(content)),
7665
Content: base64.StdEncoding.EncodeToString(content),
7766
})
7867

@@ -87,7 +76,6 @@ func Build(basePath string, discovered []DiscoveredFile, agentName string, gitCt
8776
data := Data{
8877
Agent: Agent{Name: agentName},
8978
ConfigHash: computeCombinedHash(hashes),
90-
CapturedAt: capturedAt.Format(time.RFC3339),
9179
GitContext: gitCtx,
9280
ConfigFiles: configFiles,
9381
MCPServers: mcpServers,

internal/aiagentconfig/builder_test.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import (
2626
"sort"
2727
"strings"
2828
"testing"
29-
"time"
3029

3130
"github.com/stretchr/testify/assert"
3231
"github.com/stretchr/testify/require"
@@ -51,11 +50,10 @@ func TestBuild(t *testing.T) {
5150
data, err := Build(rootDir, []DiscoveredFile{
5251
{Path: "CLAUDE.md", Kind: ConfigFileKindInstruction},
5352
{Path: ".claude/settings.json", Kind: ConfigFileKindConfiguration},
54-
}, "claude", gitCtx, time.Time{})
53+
}, "claude", gitCtx)
5554
require.NoError(t, err)
5655

5756
assert.Equal(t, "claude", data.Agent.Name)
58-
assert.NotEmpty(t, data.CapturedAt)
5957
assert.NotEmpty(t, data.ConfigHash)
6058

6159
// Verify git context
@@ -98,7 +96,7 @@ func TestBuildWithCursorAgent(t *testing.T) {
9896

9997
data, err := Build(rootDir, []DiscoveredFile{
10098
{Path: ".cursor/rules/coding.md", Kind: ConfigFileKindInstruction},
101-
}, "cursor", nil, time.Time{})
99+
}, "cursor", nil)
102100
require.NoError(t, err)
103101

104102
assert.Equal(t, "cursor", data.Agent.Name)
@@ -113,7 +111,7 @@ func TestBuildWithoutGitContext(t *testing.T) {
113111

114112
data, err := Build(rootDir, []DiscoveredFile{
115113
{Path: "CLAUDE.md", Kind: ConfigFileKindInstruction},
116-
}, "claude", nil, time.Time{})
114+
}, "claude", nil)
117115
require.NoError(t, err)
118116

119117
assert.Nil(t, data.GitContext)
@@ -126,7 +124,7 @@ func TestBuildJSONFormat(t *testing.T) {
126124

127125
data, err := Build(rootDir, []DiscoveredFile{
128126
{Path: "CLAUDE.md", Kind: ConfigFileKindInstruction},
129-
}, "claude", nil, time.Time{})
127+
}, "claude", nil)
130128
require.NoError(t, err)
131129

132130
// Verify it marshals to valid JSON with top-level fields (no envelope)
@@ -138,7 +136,6 @@ func TestBuildJSONFormat(t *testing.T) {
138136

139137
assert.NotNil(t, raw["agent"])
140138
assert.NotNil(t, raw["config_hash"])
141-
assert.NotNil(t, raw["captured_at"])
142139
assert.NotNil(t, raw["config_files"])
143140
// Ensure no envelope fields
144141
assert.Nil(t, raw["chainloop.material.evidence.id"])
@@ -161,7 +158,7 @@ func TestBuildRejectsSymlinksEscapingRoot(t *testing.T) {
161158

162159
_, err := Build(rootDir, []DiscoveredFile{
163160
{Path: "CLAUDE.md", Kind: ConfigFileKindInstruction},
164-
}, "claude", nil, time.Time{})
161+
}, "claude", nil)
165162
require.Error(t, err)
166163
assert.Contains(t, err.Error(), "path escapes root directory via symlink")
167164
}
@@ -180,25 +177,24 @@ func TestBuildRejectsSymlinkedParentDir(t *testing.T) {
180177

181178
_, err := Build(rootDir, []DiscoveredFile{
182179
{Path: ".claude/settings.json", Kind: ConfigFileKindConfiguration},
183-
}, "claude", nil, time.Time{})
180+
}, "claude", nil)
184181
require.Error(t, err)
185182
assert.Contains(t, err.Error(), "path escapes root directory via symlink")
186183
}
187184

188185
func TestBuildEmptyFileList(t *testing.T) {
189186
rootDir := t.TempDir()
190187

191-
data, err := Build(rootDir, []DiscoveredFile{}, "claude", nil, time.Time{})
188+
data, err := Build(rootDir, []DiscoveredFile{}, "claude", nil)
192189
require.NoError(t, err)
193190
assert.Empty(t, data.ConfigFiles)
194191
assert.NotEmpty(t, data.ConfigHash)
195-
assert.NotEmpty(t, data.CapturedAt)
196192
}
197193

198194
func TestBuildNilFileList(t *testing.T) {
199195
rootDir := t.TempDir()
200196

201-
data, err := Build(rootDir, nil, "claude", nil, time.Time{})
197+
data, err := Build(rootDir, nil, "claude", nil)
202198
require.NoError(t, err)
203199
assert.Empty(t, data.ConfigFiles)
204200
}
@@ -209,7 +205,7 @@ func TestBuildAllowsRegularFilesInRoot(t *testing.T) {
209205

210206
data, err := Build(rootDir, []DiscoveredFile{
211207
{Path: "CLAUDE.md", Kind: ConfigFileKindInstruction},
212-
}, "claude", nil, time.Time{})
208+
}, "claude", nil)
213209
require.NoError(t, err)
214210
assert.Len(t, data.ConfigFiles, 1)
215211
}

internal/schemavalidators/internal_schemas/aiagentconfig/ai-agent-config-0.1.schema.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
"required": [
88
"agent",
99
"config_hash",
10-
"captured_at",
1110
"config_files"
1211
],
1312
"properties": {
@@ -31,11 +30,6 @@
3130
"type": "string",
3231
"description": "SHA-256 hash of combined config for drift detection"
3332
},
34-
"captured_at": {
35-
"type": "string",
36-
"format": "date-time",
37-
"description": "Timestamp of config snapshot"
38-
},
3933
"git_context": {
4034
"type": "object",
4135
"description": "Repository, branch, commit SHA at capture time",

internal/schemavalidators/testdata/ai_agent_config_empty_config_files.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@
33
"name": "claude"
44
},
55
"config_hash": "abc123",
6-
"captured_at": "2026-03-13T10:00:00Z",
76
"config_files": []
87
}

internal/schemavalidators/testdata/ai_agent_config_extra_fields.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"name": "claude"
44
},
55
"config_hash": "abc123",
6-
"captured_at": "2026-03-13T10:00:00Z",
76
"config_files": [
87
{
98
"path": "CLAUDE.md",

internal/schemavalidators/testdata/ai_agent_config_minimal.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"name": "claude"
44
},
55
"config_hash": "abc123",
6-
"captured_at": "2026-03-13T10:00:00Z",
76
"config_files": [
87
{
98
"path": "CLAUDE.md",

internal/schemavalidators/testdata/ai_agent_config_missing_agent.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"schema_version": "0.1",
33
"config_hash": "abc123",
4-
"captured_at": "2026-03-13T10:00:00Z",
54
"config_files": [
65
{
76
"path": "CLAUDE.md",

internal/schemavalidators/testdata/ai_agent_config_missing_config_file_fields.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"name": "claude"
55
},
66
"config_hash": "abc123",
7-
"captured_at": "2026-03-13T10:00:00Z",
87
"config_files": [
98
{
109
"path": "CLAUDE.md"

internal/schemavalidators/testdata/ai_agent_config_valid.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"version": "4.0"
55
},
66
"config_hash": "abc123def456",
7-
"captured_at": "2026-03-13T10:00:00Z",
87
"git_context": {
98
"repository": "https://github.com/org/repo",
109
"branch": "main",

0 commit comments

Comments
 (0)