Integrate BACKBEAT SDK and resolve KACHING license validation

Major integrations and fixes:
- Added BACKBEAT SDK integration for P2P operation timing
- Implemented beat-aware status tracking for distributed operations
- Added Docker secrets support for secure license management
- Resolved KACHING license validation via HTTPS/TLS
- Updated docker-compose configuration for clean stack deployment
- Disabled rollback policies to prevent deployment failures
- Added license credential storage (CHORUS-DEV-MULTI-001)

Technical improvements:
- BACKBEAT P2P operation tracking with phase management
- Enhanced configuration system with file-based secrets
- Improved error handling for license validation
- Clean separation of KACHING and CHORUS deployment stacks

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-09-06 07:56:26 +10:00
parent 543ab216f9
commit 9bdcbe0447
4730 changed files with 1480093 additions and 1916 deletions

21
vendor/github.com/multiformats/go-multistream/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Jeromy Johnson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

128
vendor/github.com/multiformats/go-multistream/README.md generated vendored Normal file
View File

@@ -0,0 +1,128 @@
# go-multistream
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
[![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs)
[![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
[![GoDoc](https://godoc.org/github.com/multiformats/go-multistream?status.svg)](https://godoc.org/github.com/multiformats/go-multistream)
[![Travis CI](https://img.shields.io/travis/multiformats/go-multistream.svg?style=flat-square&branch=master)](https://travis-ci.org/multiformats/go-multistream)
[![codecov.io](https://img.shields.io/codecov/c/github/multiformats/go-multistream.svg?style=flat-square&branch=master)](https://codecov.io/github/multiformats/go-multistream?branch=master)
> an implementation of the multistream protocol in go
This package implements a simple stream router for the multistream-select protocol.
The protocol is defined [here](https://github.com/multiformats/multistream-select).
## Table of Contents
- [Install](#install)
- [Usage](#usage)
- [Maintainers](#maintainers)
- [Contribute](#contribute)
- [License](#license)
## Install
`go-multistream` is a standard Go module which can be installed with:
```sh
go get github.com/multiformats/go-multistream
```
## Usage
### Example
This example shows how to use a multistream muxer. A muxer uses user-added handlers to handle different "protocols". The first step when interacting with a connection handler by the muxer is to select the protocol (the example uses `SelectProtoOrFail`). This will then let the muxer use the right handler.
```go
package main
import (
"fmt"
"io"
"io/ioutil"
"net"
ms "github.com/multiformats/go-multistream"
)
// This example creates a multistream muxer, adds handlers for the protocols
// "/cats" and "/dogs" and exposes it on a localhost:8765. It then opens connections
// to that port, selects the protocols and tests that the handlers are working.
func main() {
mux := ms.NewMultistreamMuxer[string]()
mux.AddHandler("/cats", func(proto string, rwc io.ReadWriteCloser) error {
fmt.Fprintln(rwc, proto, ": HELLO I LIKE CATS")
return rwc.Close()
})
mux.AddHandler("/dogs", func(proto string, rwc io.ReadWriteCloser) error {
fmt.Fprintln(rwc, proto, ": HELLO I LIKE DOGS")
return rwc.Close()
})
list, err := net.Listen("tcp", ":8765")
if err != nil {
panic(err)
}
go func() {
for {
con, err := list.Accept()
if err != nil {
panic(err)
}
go mux.Handle(con)
}
}()
// The Muxer is ready, let's test it
conn, err := net.Dial("tcp", ":8765")
if err != nil {
panic(err)
}
// Create a new multistream to talk to the muxer
// which will negotiate that we want to talk with /cats
mstream := ms.NewMSSelect(conn, "/cats")
cats, err := ioutil.ReadAll(mstream)
if err != nil {
panic(err)
}
fmt.Printf("%s", cats)
mstream.Close()
// A different way of talking to the muxer
// is to manually selecting the protocol ourselves
conn, err = net.Dial("tcp", ":8765")
if err != nil {
panic(err)
}
defer conn.Close()
err = ms.SelectProtoOrFail("/dogs", conn)
if err != nil {
panic(err)
}
dogs, err := ioutil.ReadAll(conn)
if err != nil {
panic(err)
}
fmt.Printf("%s", dogs)
conn.Close()
}
```
## Contribute
Contributions welcome. Please check out [the issues](https://github.com/multiformats/go-multistream/issues).
Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
## License
[MIT](LICENSE) © 2016 Jeromy Johnson

151
vendor/github.com/multiformats/go-multistream/client.go generated vendored Normal file
View File

@@ -0,0 +1,151 @@
package multistream
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"runtime/debug"
)
// ErrNotSupported is the error returned when the muxer doesn't support
// the protocols tried for the handshake.
type ErrNotSupported[T StringLike] struct {
// Slice of protocols that were not supported by the muxer
Protos []T
}
func (e ErrNotSupported[T]) Error() string {
return fmt.Sprintf("protocols not supported: %v", e.Protos)
}
func (e ErrNotSupported[T]) Is(target error) bool {
_, ok := target.(ErrNotSupported[T])
return ok
}
// ErrNoProtocols is the error returned when the no protocols have been
// specified.
var ErrNoProtocols = errors.New("no protocols specified")
// SelectProtoOrFail performs the initial multistream handshake
// to inform the muxer of the protocol that will be used to communicate
// on this ReadWriteCloser. It returns an error if, for example,
// the muxer does not know how to handle this protocol.
func SelectProtoOrFail[T StringLike](proto T, rwc io.ReadWriteCloser) (err error) {
defer func() {
if rerr := recover(); rerr != nil {
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
err = fmt.Errorf("panic selecting protocol: %s", rerr)
}
}()
errCh := make(chan error, 1)
go func() {
var buf bytes.Buffer
if err := delitmWriteAll(&buf, []byte(ProtocolID), []byte(proto)); err != nil {
errCh <- err
return
}
_, err := io.Copy(rwc, &buf)
errCh <- err
}()
// We have to read *both* errors.
err1 := readMultistreamHeader(rwc)
err2 := readProto(proto, rwc)
if werr := <-errCh; werr != nil {
return werr
}
if err1 != nil {
return err1
}
if err2 != nil {
return err2
}
return nil
}
// SelectOneOf will perform handshakes with the protocols on the given slice
// until it finds one which is supported by the muxer.
func SelectOneOf[T StringLike](protos []T, rwc io.ReadWriteCloser) (proto T, err error) {
defer func() {
if rerr := recover(); rerr != nil {
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
err = fmt.Errorf("panic selecting one of protocols: %s", rerr)
}
}()
if len(protos) == 0 {
return "", ErrNoProtocols
}
// Use SelectProtoOrFail to pipeline the /multistream/1.0.0 handshake
// with an attempt to negotiate the first protocol. If that fails, we
// can continue negotiating the rest of the protocols normally.
//
// This saves us a round trip.
switch err := SelectProtoOrFail(protos[0], rwc); err.(type) {
case nil:
return protos[0], nil
case ErrNotSupported[T]: // try others
default:
return "", err
}
proto, err = selectProtosOrFail(protos[1:], rwc)
if _, ok := err.(ErrNotSupported[T]); ok {
return "", ErrNotSupported[T]{protos}
}
return proto, err
}
func selectProtosOrFail[T StringLike](protos []T, rwc io.ReadWriteCloser) (T, error) {
for _, p := range protos {
err := trySelect(p, rwc)
switch err := err.(type) {
case nil:
return p, nil
case ErrNotSupported[T]:
default:
return "", err
}
}
return "", ErrNotSupported[T]{protos}
}
func readMultistreamHeader(r io.Reader) error {
tok, err := ReadNextToken[string](r)
if err != nil {
return err
}
if tok != ProtocolID {
return errors.New("received mismatch in protocol id")
}
return nil
}
func trySelect[T StringLike](proto T, rwc io.ReadWriteCloser) error {
err := delimWriteBuffered(rwc, []byte(proto))
if err != nil {
return err
}
return readProto(proto, rwc)
}
func readProto[T StringLike](proto T, r io.Reader) error {
tok, err := ReadNextToken[T](r)
if err != nil {
return err
}
switch tok {
case proto:
return nil
case "na":
return ErrNotSupported[T]{[]T{proto}}
default:
return fmt.Errorf("unrecognized response: %s", tok)
}
}

View File

@@ -0,0 +1,160 @@
package multistream
import (
"fmt"
"io"
"sync"
)
// NewMSSelect returns a new Multistream which is able to perform
// protocol selection with a MultistreamMuxer.
func NewMSSelect[T StringLike](c io.ReadWriteCloser, proto T) LazyConn {
return &lazyClientConn[T]{
protos: []T{ProtocolID, proto},
con: c,
}
}
// NewMultistream returns a multistream for the given protocol. This will not
// perform any protocol selection. If you are using a MultistreamMuxer, use
// NewMSSelect.
func NewMultistream[T StringLike](c io.ReadWriteCloser, proto T) LazyConn {
return &lazyClientConn[T]{
protos: []T{proto},
con: c,
}
}
// lazyClientConn is a ReadWriteCloser adapter that lazily negotiates a protocol
// using multistream-select on first use.
//
// It *does not* block writes waiting for the other end to respond. Instead, it
// simply assumes the negotiation went successfully and starts writing data.
// See: https://github.com/multiformats/go-multistream/issues/20
type lazyClientConn[T StringLike] struct {
// Used to ensure we only trigger the write half of the handshake once.
rhandshakeOnce sync.Once
rerr error
// Used to ensure we only trigger the read half of the handshake once.
whandshakeOnce sync.Once
werr error
// The sequence of protocols to negotiate.
protos []T
// The inner connection.
con io.ReadWriteCloser
}
// Read reads data from the io.ReadWriteCloser.
//
// If the protocol hasn't yet been negotiated, this method triggers the write
// half of the handshake and then waits for the read half to complete.
//
// It returns an error if the read half of the handshake fails.
func (l *lazyClientConn[T]) Read(b []byte) (int, error) {
l.rhandshakeOnce.Do(func() {
go l.whandshakeOnce.Do(l.doWriteHandshake)
l.doReadHandshake()
})
if l.rerr != nil {
return 0, l.rerr
}
if len(b) == 0 {
return 0, nil
}
return l.con.Read(b)
}
func (l *lazyClientConn[T]) doReadHandshake() {
for _, proto := range l.protos {
// read protocol
tok, err := ReadNextToken[T](l.con)
if err != nil {
l.rerr = err
return
}
if tok == "na" {
l.rerr = ErrNotSupported[T]{[]T{proto}}
return
}
if tok != proto {
l.rerr = fmt.Errorf("protocol mismatch in lazy handshake ( %s != %s )", tok, proto)
return
}
}
}
func (l *lazyClientConn[T]) doWriteHandshake() {
l.doWriteHandshakeWithData(nil)
}
// Perform the write handshake but *also* write some extra data.
func (l *lazyClientConn[T]) doWriteHandshakeWithData(extra []byte) int {
buf := getWriter(l.con)
defer putWriter(buf)
for _, proto := range l.protos {
l.werr = delimWrite(buf, []byte(proto))
if l.werr != nil {
return 0
}
}
n := 0
if len(extra) > 0 {
n, l.werr = buf.Write(extra)
if l.werr != nil {
return n
}
}
l.werr = buf.Flush()
return n
}
// Write writes the given buffer to the underlying connection.
//
// If the protocol has not yet been negotiated, write waits for the write half
// of the handshake to complete triggers (but does not wait for) the read half.
//
// Write *also* ignores errors from the read half of the handshake (in case the
// stream is actually write only).
func (l *lazyClientConn[T]) Write(b []byte) (int, error) {
n := 0
l.whandshakeOnce.Do(func() {
go l.rhandshakeOnce.Do(l.doReadHandshake)
n = l.doWriteHandshakeWithData(b)
})
if l.werr != nil || n > 0 {
return n, l.werr
}
return l.con.Write(b)
}
// Close closes the underlying io.ReadWriteCloser
//
// This does not flush anything.
func (l *lazyClientConn[T]) Close() error {
// As the client, we flush the handshake on close to cover an
// interesting edge-case where the server only speaks a single protocol
// and responds eagerly with that protocol before waiting for out
// handshake.
//
// Again, we must not read the error because the other end may have
// closed the stream for reading. I mean, we're the initiator so that's
// strange... but it's still allowed
_ = l.Flush()
return l.con.Close()
}
// Flush sends the handshake.
func (l *lazyClientConn[T]) Flush() error {
l.whandshakeOnce.Do(func() {
go l.rhandshakeOnce.Do(l.doReadHandshake)
l.doWriteHandshake()
})
return l.werr
}

View File

@@ -0,0 +1,344 @@
// Package multistream implements a simple stream router for the
// multistream-select protocoli. The protocol is defined at
// https://github.com/multiformats/multistream-select
package multistream
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"runtime/debug"
"sync"
"github.com/multiformats/go-varint"
)
// ErrTooLarge is an error to signal that an incoming message was too large
var ErrTooLarge = errors.New("incoming message was too large")
// ProtocolID identifies the multistream protocol itself and makes sure
// the multistream muxers on both sides of a channel can work with each other.
const ProtocolID = "/multistream/1.0.0"
var writerPool = sync.Pool{
New: func() interface{} {
return bufio.NewWriter(nil)
},
}
// StringLike is an interface that supports all types with underlying type
// string
type StringLike interface {
~string
}
// HandlerFunc is a user-provided function used by the MultistreamMuxer to
// handle a protocol/stream.
type HandlerFunc[T StringLike] func(protocol T, rwc io.ReadWriteCloser) error
// Handler is a wrapper to HandlerFunc which attaches a name (protocol) and a
// match function which can optionally be used to select a handler by other
// means than the name.
type Handler[T StringLike] struct {
MatchFunc func(T) bool
Handle HandlerFunc[T]
AddName T
}
// MultistreamMuxer is a muxer for multistream. Depending on the stream
// protocol tag it will select the right handler and hand the stream off to it.
type MultistreamMuxer[T StringLike] struct {
handlerlock sync.RWMutex
handlers []Handler[T]
}
// NewMultistreamMuxer creates a muxer.
func NewMultistreamMuxer[T StringLike]() *MultistreamMuxer[T] {
return new(MultistreamMuxer[T])
}
// LazyConn is the connection type returned by the lazy negotiation functions.
type LazyConn interface {
io.ReadWriteCloser
// Flush flushes the lazy negotiation, if any.
Flush() error
}
func writeUvarint(w io.Writer, i uint64) error {
varintbuf := make([]byte, 16)
n := varint.PutUvarint(varintbuf, i)
_, err := w.Write(varintbuf[:n])
if err != nil {
return err
}
return nil
}
func delimWriteBuffered(w io.Writer, mes []byte) error {
bw := getWriter(w)
defer putWriter(bw)
err := delimWrite(bw, mes)
if err != nil {
return err
}
return bw.Flush()
}
func delitmWriteAll(w io.Writer, messages ...[]byte) error {
for _, mes := range messages {
if err := delimWrite(w, mes); err != nil {
return fmt.Errorf("failed to write messages %s, err: %v ", string(mes), err)
}
}
return nil
}
func delimWrite(w io.Writer, mes []byte) error {
err := writeUvarint(w, uint64(len(mes)+1))
if err != nil {
return err
}
_, err = w.Write(mes)
if err != nil {
return err
}
_, err = w.Write([]byte{'\n'})
if err != nil {
return err
}
return nil
}
func fulltextMatch[T StringLike](s T) func(T) bool {
return func(a T) bool {
return a == s
}
}
// AddHandler attaches a new protocol handler to the muxer.
func (msm *MultistreamMuxer[T]) AddHandler(protocol T, handler HandlerFunc[T]) {
msm.AddHandlerWithFunc(protocol, fulltextMatch(protocol), handler)
}
// AddHandlerWithFunc attaches a new protocol handler to the muxer with a match.
// If the match function returns true for a given protocol tag, the protocol
// will be selected even if the handler name and protocol tags are different.
func (msm *MultistreamMuxer[T]) AddHandlerWithFunc(protocol T, match func(T) bool, handler HandlerFunc[T]) {
msm.handlerlock.Lock()
defer msm.handlerlock.Unlock()
msm.removeHandler(protocol)
msm.handlers = append(msm.handlers, Handler[T]{
MatchFunc: match,
Handle: handler,
AddName: protocol,
})
}
// RemoveHandler removes the handler with the given name from the muxer.
func (msm *MultistreamMuxer[T]) RemoveHandler(protocol T) {
msm.handlerlock.Lock()
defer msm.handlerlock.Unlock()
msm.removeHandler(protocol)
}
func (msm *MultistreamMuxer[T]) removeHandler(protocol T) {
for i, h := range msm.handlers {
if h.AddName == protocol {
msm.handlers = append(msm.handlers[:i], msm.handlers[i+1:]...)
return
}
}
}
// Protocols returns the list of handler-names added to this this muxer.
func (msm *MultistreamMuxer[T]) Protocols() []T {
msm.handlerlock.RLock()
defer msm.handlerlock.RUnlock()
var out []T
for _, h := range msm.handlers {
out = append(out, h.AddName)
}
return out
}
// ErrIncorrectVersion is an error reported when the muxer protocol negotiation
// fails because of a ProtocolID mismatch.
var ErrIncorrectVersion = errors.New("client connected with incorrect version")
func (msm *MultistreamMuxer[T]) findHandler(proto T) *Handler[T] {
msm.handlerlock.RLock()
defer msm.handlerlock.RUnlock()
for _, h := range msm.handlers {
if h.MatchFunc(proto) {
return &h
}
}
return nil
}
// Negotiate performs protocol selection and returns the protocol name and
// the matching handler function for it (or an error).
func (msm *MultistreamMuxer[T]) Negotiate(rwc io.ReadWriteCloser) (proto T, handler HandlerFunc[T], err error) {
defer func() {
if rerr := recover(); rerr != nil {
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
err = fmt.Errorf("panic in multistream negotiation: %s", rerr)
}
}()
// Send the multistream protocol ID
// Ignore the error here. We want the handshake to finish, even if the
// other side has closed this rwc for writing. They may have sent us a
// message and closed. Future writers will get an error anyways.
_ = delimWriteBuffered(rwc, []byte(ProtocolID))
line, err := ReadNextToken[T](rwc)
if err != nil {
return "", nil, err
}
if line != ProtocolID {
rwc.Close()
return "", nil, ErrIncorrectVersion
}
loop:
for {
// Now read and respond to commands until they send a valid protocol id
tok, err := ReadNextToken[T](rwc)
if err != nil {
return "", nil, err
}
h := msm.findHandler(tok)
if h == nil {
if err := delimWriteBuffered(rwc, []byte("na")); err != nil {
return "", nil, err
}
continue loop
}
// Ignore the error here. We want the handshake to finish, even if the
// other side has closed this rwc for writing. They may have sent us a
// message and closed. Future writers will get an error anyways.
_ = delimWriteBuffered(rwc, []byte(tok))
// hand off processing to the sub-protocol handler
return tok, h.Handle, nil
}
}
// Handle performs protocol negotiation on a ReadWriteCloser
// (i.e. a connection). It will find a matching handler for the
// incoming protocol and pass the ReadWriteCloser to it.
func (msm *MultistreamMuxer[T]) Handle(rwc io.ReadWriteCloser) error {
p, h, err := msm.Negotiate(rwc)
if err != nil {
return err
}
return h(p, rwc)
}
// ReadNextToken extracts a token from a Reader. It is used during
// protocol negotiation and returns a string.
func ReadNextToken[T StringLike](r io.Reader) (T, error) {
tok, err := ReadNextTokenBytes(r)
if err != nil {
return "", err
}
return T(tok), nil
}
// ReadNextTokenBytes extracts a token from a Reader. It is used
// during protocol negotiation and returns a byte slice.
func ReadNextTokenBytes(r io.Reader) ([]byte, error) {
data, err := lpReadBuf(r)
switch err {
case nil:
return data, nil
case ErrTooLarge:
return nil, ErrTooLarge
default:
return nil, err
}
}
func lpReadBuf(r io.Reader) ([]byte, error) {
br, ok := r.(io.ByteReader)
if !ok {
br = &byteReader{r}
}
length, err := varint.ReadUvarint(br)
if err != nil {
return nil, err
}
if length > 1024 {
return nil, ErrTooLarge
}
buf := make([]byte, length)
_, err = io.ReadFull(r, buf)
if err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return nil, err
}
if len(buf) == 0 || buf[length-1] != '\n' {
return nil, errors.New("message did not have trailing newline")
}
// slice off the trailing newline
buf = buf[:length-1]
return buf, nil
}
// byteReader implements the ByteReader interface that ReadUVarint requires
type byteReader struct {
io.Reader
}
func (br *byteReader) ReadByte() (byte, error) {
var b [1]byte
n, err := br.Read(b[:])
if n == 1 {
return b[0], nil
}
if err == nil {
if n != 0 {
panic("read more bytes than buffer size")
}
err = io.ErrNoProgress
}
return 0, err
}
func getWriter(w io.Writer) *bufio.Writer {
bw := writerPool.Get().(*bufio.Writer)
bw.Reset(w)
return bw
}
func putWriter(bw *bufio.Writer) {
bw.Reset(nil)
writerPool.Put(bw)
}

View File

@@ -0,0 +1,3 @@
{
"version": "v0.4.1"
}