hancock

Check-in [a330762664]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:add role to file manifest testimony signed by author, or auditor, etc.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: a3307626647e86a2d1b9e0433643f3d83fa34c94e9e456759d2d69d9b3768629
User & Date: dnc 2019-05-27 13:33:02
Context
2019-05-27
13:54
model: improved documentation check-in: 8618055a5e user: dnc tags: trunk
13:33
add role to file manifest testimony signed by author, or auditor, etc. check-in: a330762664 user: dnc tags: trunk
2019-05-24
16:15
add timestamp to file manifest check-in: ea88da5a23 user: dnc tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to cmd/hancock/manifest.go.

22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

47
48
49
50


















51
52
53
54
55
56
57
..
72
73
74
75
76
77
78

79
80
81
82
83
84
85
// expected by `hancock-sign`.
package main

import (
	"fmt"
	"os"
	"path/filepath"

	"time"

	"github.com/pkg/errors"
	"src.d10.dev/command"
	"src.d10.dev/hancock/model"
)

func init() {
	command.RegisterOperation(command.Operation{
		Handler:     manifestMain,
		Name:        "manifest",
		Syntax:      "manifest [-r] <file or directory> [...]",
		Description: "Creates summaries of a files, suitable for signing.",
	})
}

func manifestMain() error {
	recurseFlag := command.OperationFlagSet.Bool("r", false, "descend into directories, processing all files")

	err := command.OperationFlagSet.Parse(command.Args()[1:])
	if err != nil {
		return err
	}


















	if len(command.OperationFlagSet.Args()) == 0 {
		return errors.New("Expected <file or directory> parameter.")
	}

	noRecurse := errors.New("no recurse") // prepare for filepath.Walk

	timestamp := time.Now().Unix()
................................................................................

			manifest, err := model.NewFileManifest(filepath)
			if err != nil {
				command.Error(err) // log error
				return nil         // continue walk
			}
			manifest.Time = timestamp // give all manifests the same timestamp


			// encoded manifest to stdout
			fmt.Println(mustEncode(manifest))

			return nil // continue walk
		})
		if err == noRecurse {







>











|






>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// expected by `hancock-sign`.
package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/pkg/errors"
	"src.d10.dev/command"
	"src.d10.dev/hancock/model"
)

func init() {
	command.RegisterOperation(command.Operation{
		Handler:     manifestMain,
		Name:        "manifest",
		Syntax:      "manifest [-r] [-role=<role>] <file or directory> [...]",
		Description: "Creates summaries of a files, suitable for signing.",
	})
}

func manifestMain() error {
	recurseFlag := command.OperationFlagSet.Bool("r", false, "descend into directories, processing all files")
	roleFlag := command.OperationFlagSet.String("role", "", "indicates relationship to source (i.e. author or auditor)")
	err := command.OperationFlagSet.Parse(command.Args()[1:])
	if err != nil {
		return err
	}

	// validate flags
	var role model.Role
	if *roleFlag != "" {
		roleNames := make([]string, 0, model.RoleCount)
		for i := 1; i < model.RoleCount; i++ {
			if strings.EqualFold(*roleFlag, model.Role(i).String()) {
				role = model.Role(i)
				break
			}
			roleNames = append(roleNames, model.Role(i).String())
		}
		if role == model.RoleUnknown {

			return fmt.Errorf("Unexpected role (%q).  Supported roles: %s.  Omit -role flag for %q.", *roleFlag, strings.Join(roleNames, ", "), model.RoleUnknown.String())
		}
	}

	if len(command.OperationFlagSet.Args()) == 0 {
		return errors.New("Expected <file or directory> parameter.")
	}

	noRecurse := errors.New("no recurse") // prepare for filepath.Walk

	timestamp := time.Now().Unix()
................................................................................

			manifest, err := model.NewFileManifest(filepath)
			if err != nil {
				command.Error(err) // log error
				return nil         // continue walk
			}
			manifest.Time = timestamp // give all manifests the same timestamp
			manifest.Role = role

			// encoded manifest to stdout
			fmt.Println(mustEncode(manifest))

			return nil // continue walk
		})
		if err == noRecurse {

Changes to cmd/hancock/verify.go.

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
							//	continue
							//}

							if command.V(1) {
								t := time.Unix(manifest.Time, 0)
								// TODO(dnc) format time in friendly "days ago" syntax
								if filepath != manifest.Path {
									command.Infof("%q authenticated by %q as %q on %s", filepath, authority.name, manifest.Path, t.Format(time.RFC850))
								} else {
									command.Infof("%q authenticated by %q on %s", filepath, authority.name, t.Format(time.RFC850))
								}
							}
							verified = true // TODO(dnc): consider a count of weighted authorities, rather than simple verified or not
						default:
							command.V(2).Info(filepath, u.String(), resp.Status)
							continue
						} // end ipfs status







|

|







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
							//	continue
							//}

							if command.V(1) {
								t := time.Unix(manifest.Time, 0)
								// TODO(dnc) format time in friendly "days ago" syntax
								if filepath != manifest.Path {
									command.Infof("%q authenticated by %s (%q) as %q on %s", filepath, manifest.Role, authority.name, manifest.Path, t.Format(time.RFC850))
								} else {
									command.Infof("%q authenticated by %s (%q) on %s", filepath, manifest.Role, authority.name, t.Format(time.RFC850))
								}
							}
							verified = true // TODO(dnc): consider a count of weighted authorities, rather than simple verified or not
						default:
							command.V(2).Info(filepath, u.String(), resp.Status)
							continue
						} // end ipfs status

Changes to model/manifest.go.

18
19
20
21
22
23
24



















25

26

27
28
29
30
31
32
33
34
35
import (
	"encoding/json"
	"io"
	"os"
	"time"
)




















type FileManifest struct {

	Path string `json:"path,omitempty"`

	Time int64  `json:"timestamp"`
	CID  CID    `json:"cid"`
}

func NewFileManifest(path string) (*FileManifest, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>

>

<







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
import (
	"encoding/json"
	"io"
	"os"
	"time"
)

// Role is the relationship the testifier has to the source.
type Role int

const (
	RoleUnknown Role = iota // zero

	// Author role indicates testimony provided by the author of the source.
	Author
	// Auditor role indicates testimony by a third party who has inspected the source.
	Auditor
	// Dependent role indicates testimony by a developer who includes the source as a dependency.
	Dependent

	// How many roles?
	RoleCount int = iota
)

//go:generate stringer -type=Role

type FileManifest struct {
	CID  CID    `json:"cid"`
	Path string `json:"path,omitempty"`
	Role Role   `json:"role"`
	Time int64  `json:"timestamp"`

}

func NewFileManifest(path string) (*FileManifest, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}