···14 command: |
15 mkdir -p appview/pages/static; touch appview/pages/static/x
1600000017 - name: run all tests
18 environment:
19 CGO_ENABLED: 1
···14 command: |
15 mkdir -p appview/pages/static; touch appview/pages/static/x
1617+ - name: run linter
18+ environment:
19+ CGO_ENABLED: 1
20+ command: |
21+ go vet -v ./...
22+23 - name: run all tests
24 environment:
25 CGO_ENABLED: 1
+1272-170
api/tangled/cbor_gen.go
···14991500 return nil
1501}
1502-func (t *GitRefUpdate_LangBreakdown) MarshalCBOR(w io.Writer) error {
1503 if t == nil {
1504 _, err := w.Write(cbg.CborNull)
1505 return err
1506 }
15071508 cw := cbg.NewCborWriter(w)
1509- fieldCount := 1
15101511- if t.Inputs == nil {
1512- fieldCount--
1513 }
15141515- if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
000000001516 return err
1517 }
15181519- // t.Inputs ([]*tangled.GitRefUpdate_IndividualLanguageSize) (slice)
1520- if t.Inputs != nil {
015211522- if len("inputs") > 1000000 {
1523- return xerrors.Errorf("Value in field \"inputs\" was too long")
1524- }
00015251526- if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("inputs"))); err != nil {
1527- return err
1528- }
1529- if _, err := cw.WriteString(string("inputs")); err != nil {
1530- return err
1531- }
15321533- if len(t.Inputs) > 8192 {
1534- return xerrors.Errorf("Slice value in field t.Inputs was too long")
1535- }
00015361537- if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Inputs))); err != nil {
01538 return err
1539 }
1540- for _, v := range t.Inputs {
1541- if err := v.MarshalCBOR(cw); err != nil {
1542- return err
1543- }
1544-1545 }
1546 }
01547 return nil
1548}
15491550-func (t *GitRefUpdate_LangBreakdown) UnmarshalCBOR(r io.Reader) (err error) {
1551- *t = GitRefUpdate_LangBreakdown{}
15521553 cr := cbg.NewCborReader(r)
1554···1567 }
15681569 if extra > cbg.MaxLength {
1570- return fmt.Errorf("GitRefUpdate_LangBreakdown: map struct too large (%d)", extra)
1571 }
15721573 n := extra
15741575- nameBuf := make([]byte, 6)
1576 for i := uint64(0); i < n; i++ {
1577 nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000)
1578 if err != nil {
···1588 }
15891590 switch string(nameBuf[:nameLen]) {
1591- // t.Inputs ([]*tangled.GitRefUpdate_IndividualLanguageSize) (slice)
1592- case "inputs":
1593-1594- maj, extra, err = cr.ReadHeader()
1595- if err != nil {
1596- return err
1597- }
1598-1599- if extra > 8192 {
1600- return fmt.Errorf("t.Inputs: array too large (%d)", extra)
1601- }
16021603- if maj != cbg.MajArray {
1604- return fmt.Errorf("expected cbor array")
1605- }
0016061607- if extra > 0 {
1608- t.Inputs = make([]*GitRefUpdate_IndividualLanguageSize, extra)
1609 }
1610-1611- for i := 0; i < int(extra); i++ {
1612- {
1613- var maj byte
1614- var extra uint64
1615- var err error
1616- _ = maj
1617- _ = extra
1618- _ = err
1619-1620- {
1621-1622- b, err := cr.ReadByte()
1623- if err != nil {
1624- return err
1625- }
1626- if b != cbg.CborNull[0] {
1627- if err := cr.UnreadByte(); err != nil {
1628- return err
1629- }
1630- t.Inputs[i] = new(GitRefUpdate_IndividualLanguageSize)
1631- if err := t.Inputs[i].UnmarshalCBOR(cr); err != nil {
1632- return xerrors.Errorf("unmarshaling t.Inputs[i] pointer: %w", err)
1633- }
1634- }
1635-1636 }
1637-00000001638 }
001639 }
16401641 default:
···16481649 return nil
1650}
1651-func (t *GitRefUpdate_IndividualLanguageSize) MarshalCBOR(w io.Writer) error {
1652 if t == nil {
1653 _, err := w.Write(cbg.CborNull)
1654 return err
1655 }
16561657 cw := cbg.NewCborWriter(w)
016581659- if _, err := cw.Write([]byte{162}); err != nil {
1660- return err
1661- }
1662-1663- // t.Lang (string) (string)
1664- if len("lang") > 1000000 {
1665- return xerrors.Errorf("Value in field \"lang\" was too long")
1666 }
16671668- if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("lang"))); err != nil {
1669- return err
1670- }
1671- if _, err := cw.WriteString(string("lang")); err != nil {
1672 return err
1673 }
16741675- if len(t.Lang) > 1000000 {
1676- return xerrors.Errorf("Value in field t.Lang was too long")
1677- }
16781679- if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Lang))); err != nil {
1680- return err
1681- }
1682- if _, err := cw.WriteString(string(t.Lang)); err != nil {
1683- return err
1684- }
16851686- // t.Size (int64) (int64)
1687- if len("size") > 1000000 {
1688- return xerrors.Errorf("Value in field \"size\" was too long")
1689- }
0016901691- if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("size"))); err != nil {
1692- return err
1693- }
1694- if _, err := cw.WriteString(string("size")); err != nil {
1695- return err
1696- }
16971698- if t.Size >= 0 {
1699- if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Size)); err != nil {
1700 return err
1701 }
1702- } else {
1703- if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.Size-1)); err != nil {
1704- return err
001705 }
1706 }
1707-1708 return nil
1709}
17101711-func (t *GitRefUpdate_IndividualLanguageSize) UnmarshalCBOR(r io.Reader) (err error) {
1712- *t = GitRefUpdate_IndividualLanguageSize{}
17131714 cr := cbg.NewCborReader(r)
1715···1728 }
17291730 if extra > cbg.MaxLength {
1731- return fmt.Errorf("GitRefUpdate_IndividualLanguageSize: map struct too large (%d)", extra)
1732 }
17331734 n := extra
17351736- nameBuf := make([]byte, 4)
1737 for i := uint64(0); i < n; i++ {
1738 nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000)
1739 if err != nil {
···1749 }
17501751 switch string(nameBuf[:nameLen]) {
1752- // t.Lang (string) (string)
1753- case "lang":
17541755- {
1756- sval, err := cbg.ReadStringWithMax(cr, 1000000)
1757- if err != nil {
1758- return err
1759- }
17601761- t.Lang = string(sval)
01762 }
1763- // t.Size (int64) (int64)
1764- case "size":
1765- {
1766- maj, extra, err := cr.ReadHeader()
1767- if err != nil {
1768- return err
1769- }
1770- var extraI int64
1771- switch maj {
1772- case cbg.MajUnsignedInt:
1773- extraI = int64(extra)
1774- if extraI < 0 {
1775- return fmt.Errorf("int64 positive overflow")
1776- }
1777- case cbg.MajNegativeInt:
1778- extraI = int64(extra)
1779- if extraI < 0 {
1780- return fmt.Errorf("int64 negative overflow")
00000000000000001781 }
1782- extraI = -1 - extraI
1783- default:
1784- return fmt.Errorf("wrong type for int64 field: %d", maj)
1785 }
1786-1787- t.Size = int64(extraI)
1788 }
17891790 default:
···24692470 return nil
2471}
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002472func (t *Pipeline) MarshalCBOR(w io.Writer) error {
2473 if t == nil {
2474 _, err := w.Write(cbg.CborNull)
···4756 fieldCount--
4757 }
475800004759 if t.Source == nil {
4760 fieldCount--
4761 }
···4833 return err
4834 }
48354836- // t.Owner (string) (string)
4837- if len("owner") > 1000000 {
4838- return xerrors.Errorf("Value in field \"owner\" was too long")
4839- }
00000000048404841- if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil {
4842- return err
4843- }
4844- if _, err := cw.WriteString(string("owner")); err != nil {
4845- return err
4846- }
0000048474848- if len(t.Owner) > 1000000 {
4849- return xerrors.Errorf("Value in field t.Owner was too long")
4850- }
00048514852- if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Owner))); err != nil {
4853- return err
4854- }
4855- if _, err := cw.WriteString(string(t.Owner)); err != nil {
4856- return err
4857 }
48584859 // t.Source (string) (string)
···50515052 t.LexiconTypeID = string(sval)
5053 }
5054- // t.Owner (string) (string)
5055- case "owner":
0000000000000000000000000050565057- {
5058- sval, err := cbg.ReadStringWithMax(cr, 1000000)
5059- if err != nil {
5060- return err
000005061 }
5062-5063- t.Owner = string(sval)
5064 }
5065 // t.Source (string) (string)
5066 case "source":
···14991500 return nil
1501}
1502+func (t *GitRefUpdate_IndividualLanguageSize) MarshalCBOR(w io.Writer) error {
1503 if t == nil {
1504 _, err := w.Write(cbg.CborNull)
1505 return err
1506 }
15071508 cw := cbg.NewCborWriter(w)
015091510+ if _, err := cw.Write([]byte{162}); err != nil {
1511+ return err
1512 }
15131514+ // t.Lang (string) (string)
1515+ if len("lang") > 1000000 {
1516+ return xerrors.Errorf("Value in field \"lang\" was too long")
1517+ }
1518+1519+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("lang"))); err != nil {
1520+ return err
1521+ }
1522+ if _, err := cw.WriteString(string("lang")); err != nil {
1523 return err
1524 }
15251526+ if len(t.Lang) > 1000000 {
1527+ return xerrors.Errorf("Value in field t.Lang was too long")
1528+ }
15291530+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Lang))); err != nil {
1531+ return err
1532+ }
1533+ if _, err := cw.WriteString(string(t.Lang)); err != nil {
1534+ return err
1535+ }
15361537+ // t.Size (int64) (int64)
1538+ if len("size") > 1000000 {
1539+ return xerrors.Errorf("Value in field \"size\" was too long")
1540+ }
0015411542+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("size"))); err != nil {
1543+ return err
1544+ }
1545+ if _, err := cw.WriteString(string("size")); err != nil {
1546+ return err
1547+ }
15481549+ if t.Size >= 0 {
1550+ if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Size)); err != nil {
1551 return err
1552 }
1553+ } else {
1554+ if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.Size-1)); err != nil {
1555+ return err
001556 }
1557 }
1558+1559 return nil
1560}
15611562+func (t *GitRefUpdate_IndividualLanguageSize) UnmarshalCBOR(r io.Reader) (err error) {
1563+ *t = GitRefUpdate_IndividualLanguageSize{}
15641565 cr := cbg.NewCborReader(r)
1566···1579 }
15801581 if extra > cbg.MaxLength {
1582+ return fmt.Errorf("GitRefUpdate_IndividualLanguageSize: map struct too large (%d)", extra)
1583 }
15841585 n := extra
15861587+ nameBuf := make([]byte, 4)
1588 for i := uint64(0); i < n; i++ {
1589 nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000)
1590 if err != nil {
···1600 }
16011602 switch string(nameBuf[:nameLen]) {
1603+ // t.Lang (string) (string)
1604+ case "lang":
00000000016051606+ {
1607+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
1608+ if err != nil {
1609+ return err
1610+ }
16111612+ t.Lang = string(sval)
01613 }
1614+ // t.Size (int64) (int64)
1615+ case "size":
1616+ {
1617+ maj, extra, err := cr.ReadHeader()
1618+ if err != nil {
1619+ return err
1620+ }
1621+ var extraI int64
1622+ switch maj {
1623+ case cbg.MajUnsignedInt:
1624+ extraI = int64(extra)
1625+ if extraI < 0 {
1626+ return fmt.Errorf("int64 positive overflow")
00000000000001627 }
1628+ case cbg.MajNegativeInt:
1629+ extraI = int64(extra)
1630+ if extraI < 0 {
1631+ return fmt.Errorf("int64 negative overflow")
1632+ }
1633+ extraI = -1 - extraI
1634+ default:
1635+ return fmt.Errorf("wrong type for int64 field: %d", maj)
1636 }
1637+1638+ t.Size = int64(extraI)
1639 }
16401641 default:
···16481649 return nil
1650}
1651+func (t *GitRefUpdate_LangBreakdown) MarshalCBOR(w io.Writer) error {
1652 if t == nil {
1653 _, err := w.Write(cbg.CborNull)
1654 return err
1655 }
16561657 cw := cbg.NewCborWriter(w)
1658+ fieldCount := 1
16591660+ if t.Inputs == nil {
1661+ fieldCount--
000001662 }
16631664+ if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
0001665 return err
1666 }
16671668+ // t.Inputs ([]*tangled.GitRefUpdate_IndividualLanguageSize) (slice)
1669+ if t.Inputs != nil {
016701671+ if len("inputs") > 1000000 {
1672+ return xerrors.Errorf("Value in field \"inputs\" was too long")
1673+ }
00016741675+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("inputs"))); err != nil {
1676+ return err
1677+ }
1678+ if _, err := cw.WriteString(string("inputs")); err != nil {
1679+ return err
1680+ }
16811682+ if len(t.Inputs) > 8192 {
1683+ return xerrors.Errorf("Slice value in field t.Inputs was too long")
1684+ }
00016851686+ if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Inputs))); err != nil {
01687 return err
1688 }
1689+ for _, v := range t.Inputs {
1690+ if err := v.MarshalCBOR(cw); err != nil {
1691+ return err
1692+ }
1693+1694 }
1695 }
01696 return nil
1697}
16981699+func (t *GitRefUpdate_LangBreakdown) UnmarshalCBOR(r io.Reader) (err error) {
1700+ *t = GitRefUpdate_LangBreakdown{}
17011702 cr := cbg.NewCborReader(r)
1703···1716 }
17171718 if extra > cbg.MaxLength {
1719+ return fmt.Errorf("GitRefUpdate_LangBreakdown: map struct too large (%d)", extra)
1720 }
17211722 n := extra
17231724+ nameBuf := make([]byte, 6)
1725 for i := uint64(0); i < n; i++ {
1726 nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000)
1727 if err != nil {
···1737 }
17381739 switch string(nameBuf[:nameLen]) {
1740+ // t.Inputs ([]*tangled.GitRefUpdate_IndividualLanguageSize) (slice)
1741+ case "inputs":
17421743+ maj, extra, err = cr.ReadHeader()
1744+ if err != nil {
1745+ return err
1746+ }
017471748+ if extra > 8192 {
1749+ return fmt.Errorf("t.Inputs: array too large (%d)", extra)
1750 }
1751+1752+ if maj != cbg.MajArray {
1753+ return fmt.Errorf("expected cbor array")
1754+ }
1755+1756+ if extra > 0 {
1757+ t.Inputs = make([]*GitRefUpdate_IndividualLanguageSize, extra)
1758+ }
1759+1760+ for i := 0; i < int(extra); i++ {
1761+ {
1762+ var maj byte
1763+ var extra uint64
1764+ var err error
1765+ _ = maj
1766+ _ = extra
1767+ _ = err
1768+1769+ {
1770+1771+ b, err := cr.ReadByte()
1772+ if err != nil {
1773+ return err
1774+ }
1775+ if b != cbg.CborNull[0] {
1776+ if err := cr.UnreadByte(); err != nil {
1777+ return err
1778+ }
1779+ t.Inputs[i] = new(GitRefUpdate_IndividualLanguageSize)
1780+ if err := t.Inputs[i].UnmarshalCBOR(cr); err != nil {
1781+ return xerrors.Errorf("unmarshaling t.Inputs[i] pointer: %w", err)
1782+ }
1783+ }
1784+1785 }
1786+001787 }
001788 }
17891790 default:
···24692470 return nil
2471}
2472+func (t *LabelDefinition) MarshalCBOR(w io.Writer) error {
2473+ if t == nil {
2474+ _, err := w.Write(cbg.CborNull)
2475+ return err
2476+ }
2477+2478+ cw := cbg.NewCborWriter(w)
2479+ fieldCount := 7
2480+2481+ if t.Color == nil {
2482+ fieldCount--
2483+ }
2484+2485+ if t.Multiple == nil {
2486+ fieldCount--
2487+ }
2488+2489+ if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
2490+ return err
2491+ }
2492+2493+ // t.Name (string) (string)
2494+ if len("name") > 1000000 {
2495+ return xerrors.Errorf("Value in field \"name\" was too long")
2496+ }
2497+2498+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("name"))); err != nil {
2499+ return err
2500+ }
2501+ if _, err := cw.WriteString(string("name")); err != nil {
2502+ return err
2503+ }
2504+2505+ if len(t.Name) > 1000000 {
2506+ return xerrors.Errorf("Value in field t.Name was too long")
2507+ }
2508+2509+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Name))); err != nil {
2510+ return err
2511+ }
2512+ if _, err := cw.WriteString(string(t.Name)); err != nil {
2513+ return err
2514+ }
2515+2516+ // t.LexiconTypeID (string) (string)
2517+ if len("$type") > 1000000 {
2518+ return xerrors.Errorf("Value in field \"$type\" was too long")
2519+ }
2520+2521+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil {
2522+ return err
2523+ }
2524+ if _, err := cw.WriteString(string("$type")); err != nil {
2525+ return err
2526+ }
2527+2528+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.label.definition"))); err != nil {
2529+ return err
2530+ }
2531+ if _, err := cw.WriteString(string("sh.tangled.label.definition")); err != nil {
2532+ return err
2533+ }
2534+2535+ // t.Color (string) (string)
2536+ if t.Color != nil {
2537+2538+ if len("color") > 1000000 {
2539+ return xerrors.Errorf("Value in field \"color\" was too long")
2540+ }
2541+2542+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("color"))); err != nil {
2543+ return err
2544+ }
2545+ if _, err := cw.WriteString(string("color")); err != nil {
2546+ return err
2547+ }
2548+2549+ if t.Color == nil {
2550+ if _, err := cw.Write(cbg.CborNull); err != nil {
2551+ return err
2552+ }
2553+ } else {
2554+ if len(*t.Color) > 1000000 {
2555+ return xerrors.Errorf("Value in field t.Color was too long")
2556+ }
2557+2558+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Color))); err != nil {
2559+ return err
2560+ }
2561+ if _, err := cw.WriteString(string(*t.Color)); err != nil {
2562+ return err
2563+ }
2564+ }
2565+ }
2566+2567+ // t.Scope ([]string) (slice)
2568+ if len("scope") > 1000000 {
2569+ return xerrors.Errorf("Value in field \"scope\" was too long")
2570+ }
2571+2572+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("scope"))); err != nil {
2573+ return err
2574+ }
2575+ if _, err := cw.WriteString(string("scope")); err != nil {
2576+ return err
2577+ }
2578+2579+ if len(t.Scope) > 8192 {
2580+ return xerrors.Errorf("Slice value in field t.Scope was too long")
2581+ }
2582+2583+ if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Scope))); err != nil {
2584+ return err
2585+ }
2586+ for _, v := range t.Scope {
2587+ if len(v) > 1000000 {
2588+ return xerrors.Errorf("Value in field v was too long")
2589+ }
2590+2591+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(v))); err != nil {
2592+ return err
2593+ }
2594+ if _, err := cw.WriteString(string(v)); err != nil {
2595+ return err
2596+ }
2597+2598+ }
2599+2600+ // t.Multiple (bool) (bool)
2601+ if t.Multiple != nil {
2602+2603+ if len("multiple") > 1000000 {
2604+ return xerrors.Errorf("Value in field \"multiple\" was too long")
2605+ }
2606+2607+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("multiple"))); err != nil {
2608+ return err
2609+ }
2610+ if _, err := cw.WriteString(string("multiple")); err != nil {
2611+ return err
2612+ }
2613+2614+ if t.Multiple == nil {
2615+ if _, err := cw.Write(cbg.CborNull); err != nil {
2616+ return err
2617+ }
2618+ } else {
2619+ if err := cbg.WriteBool(w, *t.Multiple); err != nil {
2620+ return err
2621+ }
2622+ }
2623+ }
2624+2625+ // t.CreatedAt (string) (string)
2626+ if len("createdAt") > 1000000 {
2627+ return xerrors.Errorf("Value in field \"createdAt\" was too long")
2628+ }
2629+2630+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("createdAt"))); err != nil {
2631+ return err
2632+ }
2633+ if _, err := cw.WriteString(string("createdAt")); err != nil {
2634+ return err
2635+ }
2636+2637+ if len(t.CreatedAt) > 1000000 {
2638+ return xerrors.Errorf("Value in field t.CreatedAt was too long")
2639+ }
2640+2641+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.CreatedAt))); err != nil {
2642+ return err
2643+ }
2644+ if _, err := cw.WriteString(string(t.CreatedAt)); err != nil {
2645+ return err
2646+ }
2647+2648+ // t.ValueType (tangled.LabelDefinition_ValueType) (struct)
2649+ if len("valueType") > 1000000 {
2650+ return xerrors.Errorf("Value in field \"valueType\" was too long")
2651+ }
2652+2653+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("valueType"))); err != nil {
2654+ return err
2655+ }
2656+ if _, err := cw.WriteString(string("valueType")); err != nil {
2657+ return err
2658+ }
2659+2660+ if err := t.ValueType.MarshalCBOR(cw); err != nil {
2661+ return err
2662+ }
2663+ return nil
2664+}
2665+2666+func (t *LabelDefinition) UnmarshalCBOR(r io.Reader) (err error) {
2667+ *t = LabelDefinition{}
2668+2669+ cr := cbg.NewCborReader(r)
2670+2671+ maj, extra, err := cr.ReadHeader()
2672+ if err != nil {
2673+ return err
2674+ }
2675+ defer func() {
2676+ if err == io.EOF {
2677+ err = io.ErrUnexpectedEOF
2678+ }
2679+ }()
2680+2681+ if maj != cbg.MajMap {
2682+ return fmt.Errorf("cbor input should be of type map")
2683+ }
2684+2685+ if extra > cbg.MaxLength {
2686+ return fmt.Errorf("LabelDefinition: map struct too large (%d)", extra)
2687+ }
2688+2689+ n := extra
2690+2691+ nameBuf := make([]byte, 9)
2692+ for i := uint64(0); i < n; i++ {
2693+ nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000)
2694+ if err != nil {
2695+ return err
2696+ }
2697+2698+ if !ok {
2699+ // Field doesn't exist on this type, so ignore it
2700+ if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil {
2701+ return err
2702+ }
2703+ continue
2704+ }
2705+2706+ switch string(nameBuf[:nameLen]) {
2707+ // t.Name (string) (string)
2708+ case "name":
2709+2710+ {
2711+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
2712+ if err != nil {
2713+ return err
2714+ }
2715+2716+ t.Name = string(sval)
2717+ }
2718+ // t.LexiconTypeID (string) (string)
2719+ case "$type":
2720+2721+ {
2722+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
2723+ if err != nil {
2724+ return err
2725+ }
2726+2727+ t.LexiconTypeID = string(sval)
2728+ }
2729+ // t.Color (string) (string)
2730+ case "color":
2731+2732+ {
2733+ b, err := cr.ReadByte()
2734+ if err != nil {
2735+ return err
2736+ }
2737+ if b != cbg.CborNull[0] {
2738+ if err := cr.UnreadByte(); err != nil {
2739+ return err
2740+ }
2741+2742+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
2743+ if err != nil {
2744+ return err
2745+ }
2746+2747+ t.Color = (*string)(&sval)
2748+ }
2749+ }
2750+ // t.Scope ([]string) (slice)
2751+ case "scope":
2752+2753+ maj, extra, err = cr.ReadHeader()
2754+ if err != nil {
2755+ return err
2756+ }
2757+2758+ if extra > 8192 {
2759+ return fmt.Errorf("t.Scope: array too large (%d)", extra)
2760+ }
2761+2762+ if maj != cbg.MajArray {
2763+ return fmt.Errorf("expected cbor array")
2764+ }
2765+2766+ if extra > 0 {
2767+ t.Scope = make([]string, extra)
2768+ }
2769+2770+ for i := 0; i < int(extra); i++ {
2771+ {
2772+ var maj byte
2773+ var extra uint64
2774+ var err error
2775+ _ = maj
2776+ _ = extra
2777+ _ = err
2778+2779+ {
2780+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
2781+ if err != nil {
2782+ return err
2783+ }
2784+2785+ t.Scope[i] = string(sval)
2786+ }
2787+2788+ }
2789+ }
2790+ // t.Multiple (bool) (bool)
2791+ case "multiple":
2792+2793+ {
2794+ b, err := cr.ReadByte()
2795+ if err != nil {
2796+ return err
2797+ }
2798+ if b != cbg.CborNull[0] {
2799+ if err := cr.UnreadByte(); err != nil {
2800+ return err
2801+ }
2802+2803+ maj, extra, err = cr.ReadHeader()
2804+ if err != nil {
2805+ return err
2806+ }
2807+ if maj != cbg.MajOther {
2808+ return fmt.Errorf("booleans must be major type 7")
2809+ }
2810+2811+ var val bool
2812+ switch extra {
2813+ case 20:
2814+ val = false
2815+ case 21:
2816+ val = true
2817+ default:
2818+ return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra)
2819+ }
2820+ t.Multiple = &val
2821+ }
2822+ }
2823+ // t.CreatedAt (string) (string)
2824+ case "createdAt":
2825+2826+ {
2827+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
2828+ if err != nil {
2829+ return err
2830+ }
2831+2832+ t.CreatedAt = string(sval)
2833+ }
2834+ // t.ValueType (tangled.LabelDefinition_ValueType) (struct)
2835+ case "valueType":
2836+2837+ {
2838+2839+ b, err := cr.ReadByte()
2840+ if err != nil {
2841+ return err
2842+ }
2843+ if b != cbg.CborNull[0] {
2844+ if err := cr.UnreadByte(); err != nil {
2845+ return err
2846+ }
2847+ t.ValueType = new(LabelDefinition_ValueType)
2848+ if err := t.ValueType.UnmarshalCBOR(cr); err != nil {
2849+ return xerrors.Errorf("unmarshaling t.ValueType pointer: %w", err)
2850+ }
2851+ }
2852+2853+ }
2854+2855+ default:
2856+ // Field doesn't exist on this type, so ignore it
2857+ if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil {
2858+ return err
2859+ }
2860+ }
2861+ }
2862+2863+ return nil
2864+}
2865+func (t *LabelDefinition_ValueType) MarshalCBOR(w io.Writer) error {
2866+ if t == nil {
2867+ _, err := w.Write(cbg.CborNull)
2868+ return err
2869+ }
2870+2871+ cw := cbg.NewCborWriter(w)
2872+ fieldCount := 3
2873+2874+ if t.Enum == nil {
2875+ fieldCount--
2876+ }
2877+2878+ if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
2879+ return err
2880+ }
2881+2882+ // t.Enum ([]string) (slice)
2883+ if t.Enum != nil {
2884+2885+ if len("enum") > 1000000 {
2886+ return xerrors.Errorf("Value in field \"enum\" was too long")
2887+ }
2888+2889+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("enum"))); err != nil {
2890+ return err
2891+ }
2892+ if _, err := cw.WriteString(string("enum")); err != nil {
2893+ return err
2894+ }
2895+2896+ if len(t.Enum) > 8192 {
2897+ return xerrors.Errorf("Slice value in field t.Enum was too long")
2898+ }
2899+2900+ if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Enum))); err != nil {
2901+ return err
2902+ }
2903+ for _, v := range t.Enum {
2904+ if len(v) > 1000000 {
2905+ return xerrors.Errorf("Value in field v was too long")
2906+ }
2907+2908+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(v))); err != nil {
2909+ return err
2910+ }
2911+ if _, err := cw.WriteString(string(v)); err != nil {
2912+ return err
2913+ }
2914+2915+ }
2916+ }
2917+2918+ // t.Type (string) (string)
2919+ if len("type") > 1000000 {
2920+ return xerrors.Errorf("Value in field \"type\" was too long")
2921+ }
2922+2923+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("type"))); err != nil {
2924+ return err
2925+ }
2926+ if _, err := cw.WriteString(string("type")); err != nil {
2927+ return err
2928+ }
2929+2930+ if len(t.Type) > 1000000 {
2931+ return xerrors.Errorf("Value in field t.Type was too long")
2932+ }
2933+2934+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Type))); err != nil {
2935+ return err
2936+ }
2937+ if _, err := cw.WriteString(string(t.Type)); err != nil {
2938+ return err
2939+ }
2940+2941+ // t.Format (string) (string)
2942+ if len("format") > 1000000 {
2943+ return xerrors.Errorf("Value in field \"format\" was too long")
2944+ }
2945+2946+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("format"))); err != nil {
2947+ return err
2948+ }
2949+ if _, err := cw.WriteString(string("format")); err != nil {
2950+ return err
2951+ }
2952+2953+ if len(t.Format) > 1000000 {
2954+ return xerrors.Errorf("Value in field t.Format was too long")
2955+ }
2956+2957+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Format))); err != nil {
2958+ return err
2959+ }
2960+ if _, err := cw.WriteString(string(t.Format)); err != nil {
2961+ return err
2962+ }
2963+ return nil
2964+}
2965+2966+func (t *LabelDefinition_ValueType) UnmarshalCBOR(r io.Reader) (err error) {
2967+ *t = LabelDefinition_ValueType{}
2968+2969+ cr := cbg.NewCborReader(r)
2970+2971+ maj, extra, err := cr.ReadHeader()
2972+ if err != nil {
2973+ return err
2974+ }
2975+ defer func() {
2976+ if err == io.EOF {
2977+ err = io.ErrUnexpectedEOF
2978+ }
2979+ }()
2980+2981+ if maj != cbg.MajMap {
2982+ return fmt.Errorf("cbor input should be of type map")
2983+ }
2984+2985+ if extra > cbg.MaxLength {
2986+ return fmt.Errorf("LabelDefinition_ValueType: map struct too large (%d)", extra)
2987+ }
2988+2989+ n := extra
2990+2991+ nameBuf := make([]byte, 6)
2992+ for i := uint64(0); i < n; i++ {
2993+ nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000)
2994+ if err != nil {
2995+ return err
2996+ }
2997+2998+ if !ok {
2999+ // Field doesn't exist on this type, so ignore it
3000+ if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil {
3001+ return err
3002+ }
3003+ continue
3004+ }
3005+3006+ switch string(nameBuf[:nameLen]) {
3007+ // t.Enum ([]string) (slice)
3008+ case "enum":
3009+3010+ maj, extra, err = cr.ReadHeader()
3011+ if err != nil {
3012+ return err
3013+ }
3014+3015+ if extra > 8192 {
3016+ return fmt.Errorf("t.Enum: array too large (%d)", extra)
3017+ }
3018+3019+ if maj != cbg.MajArray {
3020+ return fmt.Errorf("expected cbor array")
3021+ }
3022+3023+ if extra > 0 {
3024+ t.Enum = make([]string, extra)
3025+ }
3026+3027+ for i := 0; i < int(extra); i++ {
3028+ {
3029+ var maj byte
3030+ var extra uint64
3031+ var err error
3032+ _ = maj
3033+ _ = extra
3034+ _ = err
3035+3036+ {
3037+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
3038+ if err != nil {
3039+ return err
3040+ }
3041+3042+ t.Enum[i] = string(sval)
3043+ }
3044+3045+ }
3046+ }
3047+ // t.Type (string) (string)
3048+ case "type":
3049+3050+ {
3051+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
3052+ if err != nil {
3053+ return err
3054+ }
3055+3056+ t.Type = string(sval)
3057+ }
3058+ // t.Format (string) (string)
3059+ case "format":
3060+3061+ {
3062+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
3063+ if err != nil {
3064+ return err
3065+ }
3066+3067+ t.Format = string(sval)
3068+ }
3069+3070+ default:
3071+ // Field doesn't exist on this type, so ignore it
3072+ if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil {
3073+ return err
3074+ }
3075+ }
3076+ }
3077+3078+ return nil
3079+}
3080+func (t *LabelOp) MarshalCBOR(w io.Writer) error {
3081+ if t == nil {
3082+ _, err := w.Write(cbg.CborNull)
3083+ return err
3084+ }
3085+3086+ cw := cbg.NewCborWriter(w)
3087+3088+ if _, err := cw.Write([]byte{165}); err != nil {
3089+ return err
3090+ }
3091+3092+ // t.Add ([]*tangled.LabelOp_Operand) (slice)
3093+ if len("add") > 1000000 {
3094+ return xerrors.Errorf("Value in field \"add\" was too long")
3095+ }
3096+3097+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("add"))); err != nil {
3098+ return err
3099+ }
3100+ if _, err := cw.WriteString(string("add")); err != nil {
3101+ return err
3102+ }
3103+3104+ if len(t.Add) > 8192 {
3105+ return xerrors.Errorf("Slice value in field t.Add was too long")
3106+ }
3107+3108+ if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Add))); err != nil {
3109+ return err
3110+ }
3111+ for _, v := range t.Add {
3112+ if err := v.MarshalCBOR(cw); err != nil {
3113+ return err
3114+ }
3115+3116+ }
3117+3118+ // t.LexiconTypeID (string) (string)
3119+ if len("$type") > 1000000 {
3120+ return xerrors.Errorf("Value in field \"$type\" was too long")
3121+ }
3122+3123+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil {
3124+ return err
3125+ }
3126+ if _, err := cw.WriteString(string("$type")); err != nil {
3127+ return err
3128+ }
3129+3130+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.label.op"))); err != nil {
3131+ return err
3132+ }
3133+ if _, err := cw.WriteString(string("sh.tangled.label.op")); err != nil {
3134+ return err
3135+ }
3136+3137+ // t.Delete ([]*tangled.LabelOp_Operand) (slice)
3138+ if len("delete") > 1000000 {
3139+ return xerrors.Errorf("Value in field \"delete\" was too long")
3140+ }
3141+3142+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("delete"))); err != nil {
3143+ return err
3144+ }
3145+ if _, err := cw.WriteString(string("delete")); err != nil {
3146+ return err
3147+ }
3148+3149+ if len(t.Delete) > 8192 {
3150+ return xerrors.Errorf("Slice value in field t.Delete was too long")
3151+ }
3152+3153+ if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Delete))); err != nil {
3154+ return err
3155+ }
3156+ for _, v := range t.Delete {
3157+ if err := v.MarshalCBOR(cw); err != nil {
3158+ return err
3159+ }
3160+3161+ }
3162+3163+ // t.Subject (string) (string)
3164+ if len("subject") > 1000000 {
3165+ return xerrors.Errorf("Value in field \"subject\" was too long")
3166+ }
3167+3168+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("subject"))); err != nil {
3169+ return err
3170+ }
3171+ if _, err := cw.WriteString(string("subject")); err != nil {
3172+ return err
3173+ }
3174+3175+ if len(t.Subject) > 1000000 {
3176+ return xerrors.Errorf("Value in field t.Subject was too long")
3177+ }
3178+3179+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Subject))); err != nil {
3180+ return err
3181+ }
3182+ if _, err := cw.WriteString(string(t.Subject)); err != nil {
3183+ return err
3184+ }
3185+3186+ // t.PerformedAt (string) (string)
3187+ if len("performedAt") > 1000000 {
3188+ return xerrors.Errorf("Value in field \"performedAt\" was too long")
3189+ }
3190+3191+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("performedAt"))); err != nil {
3192+ return err
3193+ }
3194+ if _, err := cw.WriteString(string("performedAt")); err != nil {
3195+ return err
3196+ }
3197+3198+ if len(t.PerformedAt) > 1000000 {
3199+ return xerrors.Errorf("Value in field t.PerformedAt was too long")
3200+ }
3201+3202+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.PerformedAt))); err != nil {
3203+ return err
3204+ }
3205+ if _, err := cw.WriteString(string(t.PerformedAt)); err != nil {
3206+ return err
3207+ }
3208+ return nil
3209+}
3210+3211+func (t *LabelOp) UnmarshalCBOR(r io.Reader) (err error) {
3212+ *t = LabelOp{}
3213+3214+ cr := cbg.NewCborReader(r)
3215+3216+ maj, extra, err := cr.ReadHeader()
3217+ if err != nil {
3218+ return err
3219+ }
3220+ defer func() {
3221+ if err == io.EOF {
3222+ err = io.ErrUnexpectedEOF
3223+ }
3224+ }()
3225+3226+ if maj != cbg.MajMap {
3227+ return fmt.Errorf("cbor input should be of type map")
3228+ }
3229+3230+ if extra > cbg.MaxLength {
3231+ return fmt.Errorf("LabelOp: map struct too large (%d)", extra)
3232+ }
3233+3234+ n := extra
3235+3236+ nameBuf := make([]byte, 11)
3237+ for i := uint64(0); i < n; i++ {
3238+ nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000)
3239+ if err != nil {
3240+ return err
3241+ }
3242+3243+ if !ok {
3244+ // Field doesn't exist on this type, so ignore it
3245+ if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil {
3246+ return err
3247+ }
3248+ continue
3249+ }
3250+3251+ switch string(nameBuf[:nameLen]) {
3252+ // t.Add ([]*tangled.LabelOp_Operand) (slice)
3253+ case "add":
3254+3255+ maj, extra, err = cr.ReadHeader()
3256+ if err != nil {
3257+ return err
3258+ }
3259+3260+ if extra > 8192 {
3261+ return fmt.Errorf("t.Add: array too large (%d)", extra)
3262+ }
3263+3264+ if maj != cbg.MajArray {
3265+ return fmt.Errorf("expected cbor array")
3266+ }
3267+3268+ if extra > 0 {
3269+ t.Add = make([]*LabelOp_Operand, extra)
3270+ }
3271+3272+ for i := 0; i < int(extra); i++ {
3273+ {
3274+ var maj byte
3275+ var extra uint64
3276+ var err error
3277+ _ = maj
3278+ _ = extra
3279+ _ = err
3280+3281+ {
3282+3283+ b, err := cr.ReadByte()
3284+ if err != nil {
3285+ return err
3286+ }
3287+ if b != cbg.CborNull[0] {
3288+ if err := cr.UnreadByte(); err != nil {
3289+ return err
3290+ }
3291+ t.Add[i] = new(LabelOp_Operand)
3292+ if err := t.Add[i].UnmarshalCBOR(cr); err != nil {
3293+ return xerrors.Errorf("unmarshaling t.Add[i] pointer: %w", err)
3294+ }
3295+ }
3296+3297+ }
3298+3299+ }
3300+ }
3301+ // t.LexiconTypeID (string) (string)
3302+ case "$type":
3303+3304+ {
3305+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
3306+ if err != nil {
3307+ return err
3308+ }
3309+3310+ t.LexiconTypeID = string(sval)
3311+ }
3312+ // t.Delete ([]*tangled.LabelOp_Operand) (slice)
3313+ case "delete":
3314+3315+ maj, extra, err = cr.ReadHeader()
3316+ if err != nil {
3317+ return err
3318+ }
3319+3320+ if extra > 8192 {
3321+ return fmt.Errorf("t.Delete: array too large (%d)", extra)
3322+ }
3323+3324+ if maj != cbg.MajArray {
3325+ return fmt.Errorf("expected cbor array")
3326+ }
3327+3328+ if extra > 0 {
3329+ t.Delete = make([]*LabelOp_Operand, extra)
3330+ }
3331+3332+ for i := 0; i < int(extra); i++ {
3333+ {
3334+ var maj byte
3335+ var extra uint64
3336+ var err error
3337+ _ = maj
3338+ _ = extra
3339+ _ = err
3340+3341+ {
3342+3343+ b, err := cr.ReadByte()
3344+ if err != nil {
3345+ return err
3346+ }
3347+ if b != cbg.CborNull[0] {
3348+ if err := cr.UnreadByte(); err != nil {
3349+ return err
3350+ }
3351+ t.Delete[i] = new(LabelOp_Operand)
3352+ if err := t.Delete[i].UnmarshalCBOR(cr); err != nil {
3353+ return xerrors.Errorf("unmarshaling t.Delete[i] pointer: %w", err)
3354+ }
3355+ }
3356+3357+ }
3358+3359+ }
3360+ }
3361+ // t.Subject (string) (string)
3362+ case "subject":
3363+3364+ {
3365+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
3366+ if err != nil {
3367+ return err
3368+ }
3369+3370+ t.Subject = string(sval)
3371+ }
3372+ // t.PerformedAt (string) (string)
3373+ case "performedAt":
3374+3375+ {
3376+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
3377+ if err != nil {
3378+ return err
3379+ }
3380+3381+ t.PerformedAt = string(sval)
3382+ }
3383+3384+ default:
3385+ // Field doesn't exist on this type, so ignore it
3386+ if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil {
3387+ return err
3388+ }
3389+ }
3390+ }
3391+3392+ return nil
3393+}
3394+func (t *LabelOp_Operand) MarshalCBOR(w io.Writer) error {
3395+ if t == nil {
3396+ _, err := w.Write(cbg.CborNull)
3397+ return err
3398+ }
3399+3400+ cw := cbg.NewCborWriter(w)
3401+3402+ if _, err := cw.Write([]byte{162}); err != nil {
3403+ return err
3404+ }
3405+3406+ // t.Key (string) (string)
3407+ if len("key") > 1000000 {
3408+ return xerrors.Errorf("Value in field \"key\" was too long")
3409+ }
3410+3411+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("key"))); err != nil {
3412+ return err
3413+ }
3414+ if _, err := cw.WriteString(string("key")); err != nil {
3415+ return err
3416+ }
3417+3418+ if len(t.Key) > 1000000 {
3419+ return xerrors.Errorf("Value in field t.Key was too long")
3420+ }
3421+3422+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Key))); err != nil {
3423+ return err
3424+ }
3425+ if _, err := cw.WriteString(string(t.Key)); err != nil {
3426+ return err
3427+ }
3428+3429+ // t.Value (string) (string)
3430+ if len("value") > 1000000 {
3431+ return xerrors.Errorf("Value in field \"value\" was too long")
3432+ }
3433+3434+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("value"))); err != nil {
3435+ return err
3436+ }
3437+ if _, err := cw.WriteString(string("value")); err != nil {
3438+ return err
3439+ }
3440+3441+ if len(t.Value) > 1000000 {
3442+ return xerrors.Errorf("Value in field t.Value was too long")
3443+ }
3444+3445+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Value))); err != nil {
3446+ return err
3447+ }
3448+ if _, err := cw.WriteString(string(t.Value)); err != nil {
3449+ return err
3450+ }
3451+ return nil
3452+}
3453+3454+func (t *LabelOp_Operand) UnmarshalCBOR(r io.Reader) (err error) {
3455+ *t = LabelOp_Operand{}
3456+3457+ cr := cbg.NewCborReader(r)
3458+3459+ maj, extra, err := cr.ReadHeader()
3460+ if err != nil {
3461+ return err
3462+ }
3463+ defer func() {
3464+ if err == io.EOF {
3465+ err = io.ErrUnexpectedEOF
3466+ }
3467+ }()
3468+3469+ if maj != cbg.MajMap {
3470+ return fmt.Errorf("cbor input should be of type map")
3471+ }
3472+3473+ if extra > cbg.MaxLength {
3474+ return fmt.Errorf("LabelOp_Operand: map struct too large (%d)", extra)
3475+ }
3476+3477+ n := extra
3478+3479+ nameBuf := make([]byte, 5)
3480+ for i := uint64(0); i < n; i++ {
3481+ nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000)
3482+ if err != nil {
3483+ return err
3484+ }
3485+3486+ if !ok {
3487+ // Field doesn't exist on this type, so ignore it
3488+ if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil {
3489+ return err
3490+ }
3491+ continue
3492+ }
3493+3494+ switch string(nameBuf[:nameLen]) {
3495+ // t.Key (string) (string)
3496+ case "key":
3497+3498+ {
3499+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
3500+ if err != nil {
3501+ return err
3502+ }
3503+3504+ t.Key = string(sval)
3505+ }
3506+ // t.Value (string) (string)
3507+ case "value":
3508+3509+ {
3510+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
3511+ if err != nil {
3512+ return err
3513+ }
3514+3515+ t.Value = string(sval)
3516+ }
3517+3518+ default:
3519+ // Field doesn't exist on this type, so ignore it
3520+ if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil {
3521+ return err
3522+ }
3523+ }
3524+ }
3525+3526+ return nil
3527+}
3528func (t *Pipeline) MarshalCBOR(w io.Writer) error {
3529 if t == nil {
3530 _, err := w.Write(cbg.CborNull)
···5812 fieldCount--
5813 }
58145815+ if t.Labels == nil {
5816+ fieldCount--
5817+ }
5818+5819 if t.Source == nil {
5820 fieldCount--
5821 }
···5893 return err
5894 }
58955896+ // t.Labels ([]string) (slice)
5897+ if t.Labels != nil {
5898+5899+ if len("labels") > 1000000 {
5900+ return xerrors.Errorf("Value in field \"labels\" was too long")
5901+ }
5902+5903+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("labels"))); err != nil {
5904+ return err
5905+ }
5906+ if _, err := cw.WriteString(string("labels")); err != nil {
5907+ return err
5908+ }
59095910+ if len(t.Labels) > 8192 {
5911+ return xerrors.Errorf("Slice value in field t.Labels was too long")
5912+ }
5913+5914+ if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Labels))); err != nil {
5915+ return err
5916+ }
5917+ for _, v := range t.Labels {
5918+ if len(v) > 1000000 {
5919+ return xerrors.Errorf("Value in field v was too long")
5920+ }
59215922+ if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(v))); err != nil {
5923+ return err
5924+ }
5925+ if _, err := cw.WriteString(string(v)); err != nil {
5926+ return err
5927+ }
59285929+ }
00005930 }
59315932 // t.Source (string) (string)
···61246125 t.LexiconTypeID = string(sval)
6126 }
6127+ // t.Labels ([]string) (slice)
6128+ case "labels":
6129+6130+ maj, extra, err = cr.ReadHeader()
6131+ if err != nil {
6132+ return err
6133+ }
6134+6135+ if extra > 8192 {
6136+ return fmt.Errorf("t.Labels: array too large (%d)", extra)
6137+ }
6138+6139+ if maj != cbg.MajArray {
6140+ return fmt.Errorf("expected cbor array")
6141+ }
6142+6143+ if extra > 0 {
6144+ t.Labels = make([]string, extra)
6145+ }
6146+6147+ for i := 0; i < int(extra); i++ {
6148+ {
6149+ var maj byte
6150+ var extra uint64
6151+ var err error
6152+ _ = maj
6153+ _ = extra
6154+ _ = err
61556156+ {
6157+ sval, err := cbg.ReadStringWithMax(cr, 1000000)
6158+ if err != nil {
6159+ return err
6160+ }
6161+6162+ t.Labels[i] = string(sval)
6163+ }
6164+6165 }
006166 }
6167 // t.Source (string) (string)
6168 case "source":
+42
api/tangled/labeldefinition.go
···000000000000000000000000000000000000000000
···1+// Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT.
2+3+package tangled
4+5+// schema: sh.tangled.label.definition
6+7+import (
8+ "github.com/bluesky-social/indigo/lex/util"
9+)
10+11+const (
12+ LabelDefinitionNSID = "sh.tangled.label.definition"
13+)
14+15+func init() {
16+ util.RegisterType("sh.tangled.label.definition", &LabelDefinition{})
17+} //
18+// RECORDTYPE: LabelDefinition
19+type LabelDefinition struct {
20+ LexiconTypeID string `json:"$type,const=sh.tangled.label.definition" cborgen:"$type,const=sh.tangled.label.definition"`
21+ // color: The hex value for the background color for the label. Appviews may choose to respect this.
22+ Color *string `json:"color,omitempty" cborgen:"color,omitempty"`
23+ CreatedAt string `json:"createdAt" cborgen:"createdAt"`
24+ // multiple: Whether this label can be repeated for a given entity, eg.: [reviewer:foo, reviewer:bar]
25+ Multiple *bool `json:"multiple,omitempty" cborgen:"multiple,omitempty"`
26+ // name: The display name of this label.
27+ Name string `json:"name" cborgen:"name"`
28+ // scope: The areas of the repo this label may apply to, eg.: sh.tangled.repo.issue. Appviews may choose to respect this.
29+ Scope []string `json:"scope" cborgen:"scope"`
30+ // valueType: The type definition of this label. Appviews may allow sorting for certain types.
31+ ValueType *LabelDefinition_ValueType `json:"valueType" cborgen:"valueType"`
32+}
33+34+// LabelDefinition_ValueType is a "valueType" in the sh.tangled.label.definition schema.
35+type LabelDefinition_ValueType struct {
36+ // enum: Closed set of values that this label can take.
37+ Enum []string `json:"enum,omitempty" cborgen:"enum,omitempty"`
38+ // format: An optional constraint that can be applied on string concrete types.
39+ Format string `json:"format" cborgen:"format"`
40+ // type: The concrete type of this label's value.
41+ Type string `json:"type" cborgen:"type"`
42+}
+34
api/tangled/labelop.go
···0000000000000000000000000000000000
···1+// Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT.
2+3+package tangled
4+5+// schema: sh.tangled.label.op
6+7+import (
8+ "github.com/bluesky-social/indigo/lex/util"
9+)
10+11+const (
12+ LabelOpNSID = "sh.tangled.label.op"
13+)
14+15+func init() {
16+ util.RegisterType("sh.tangled.label.op", &LabelOp{})
17+} //
18+// RECORDTYPE: LabelOp
19+type LabelOp struct {
20+ LexiconTypeID string `json:"$type,const=sh.tangled.label.op" cborgen:"$type,const=sh.tangled.label.op"`
21+ Add []*LabelOp_Operand `json:"add" cborgen:"add"`
22+ Delete []*LabelOp_Operand `json:"delete" cborgen:"delete"`
23+ PerformedAt string `json:"performedAt" cborgen:"performedAt"`
24+ // subject: The subject (task, pull or discussion) of this label. Appviews may apply a `scope` check and refuse this op.
25+ Subject string `json:"subject" cborgen:"subject"`
26+}
27+28+// LabelOp_Operand is a "operand" in the sh.tangled.label.op schema.
29+type LabelOp_Operand struct {
30+ // key: ATURI to the label definition
31+ Key string `json:"key" cborgen:"key"`
32+ // value: Stringified value of the label. This is first unstringed by appviews and then interpreted as a concrete value.
33+ Value string `json:"value" cborgen:"value"`
34+}
+10
api/tangled/repotree.go
···31 Files []*RepoTree_TreeEntry `json:"files" cborgen:"files"`
32 // parent: The parent path in the tree
33 Parent *string `json:"parent,omitempty" cborgen:"parent,omitempty"`
0034 // ref: The git reference used
35 Ref string `json:"ref" cborgen:"ref"`
0000000036}
3738// RepoTree_TreeEntry is a "treeEntry" in the sh.tangled.repo.tree schema.
···31 Files []*RepoTree_TreeEntry `json:"files" cborgen:"files"`
32 // parent: The parent path in the tree
33 Parent *string `json:"parent,omitempty" cborgen:"parent,omitempty"`
34+ // readme: Readme for this file tree
35+ Readme *RepoTree_Readme `json:"readme,omitempty" cborgen:"readme,omitempty"`
36 // ref: The git reference used
37 Ref string `json:"ref" cborgen:"ref"`
38+}
39+40+// RepoTree_Readme is a "readme" in the sh.tangled.repo.tree schema.
41+type RepoTree_Readme struct {
42+ // contents: Contents of the readme file
43+ Contents string `json:"contents" cborgen:"contents"`
44+ // filename: Name of the readme file
45+ Filename string `json:"filename" cborgen:"filename"`
46}
4748// RepoTree_TreeEntry is a "treeEntry" in the sh.tangled.repo.tree schema.
+3-2
api/tangled/tangledrepo.go
···22 Description *string `json:"description,omitempty" cborgen:"description,omitempty"`
23 // knot: knot where the repo was created
24 Knot string `json:"knot" cborgen:"knot"`
0025 // name: name of the repo
26- Name string `json:"name" cborgen:"name"`
27- Owner string `json:"owner" cborgen:"owner"`
28 // source: source of the repo
29 Source *string `json:"source,omitempty" cborgen:"source,omitempty"`
30 // spindle: CI runner to send jobs to and receive results from
···22 Description *string `json:"description,omitempty" cborgen:"description,omitempty"`
23 // knot: knot where the repo was created
24 Knot string `json:"knot" cborgen:"knot"`
25+ // labels: List of labels that this repo subscribes to
26+ Labels []string `json:"labels,omitempty" cborgen:"labels,omitempty"`
27 // name: name of the repo
28+ Name string `json:"name" cborgen:"name"`
029 // source: source of the repo
30 Source *string `json:"source,omitempty" cborgen:"source,omitempty"`
31 // spindle: CI runner to send jobs to and receive results from
···6 "strings"
7 "time"
89- "github.com/bluesky-social/indigo/atproto/syntax"
10)
1112-type Spindle struct {
13- Id int
14- Owner syntax.DID
15- Instance string
16- Verified *time.Time
17- Created time.Time
18- NeedsUpgrade bool
19-}
20-21-type SpindleMember struct {
22- Id int
23- Did syntax.DID // owner of the record
24- Rkey string // rkey of the record
25- Instance string
26- Subject syntax.DID // the member being added
27- Created time.Time
28-}
29-30-func GetSpindles(e Execer, filters ...filter) ([]Spindle, error) {
31- var spindles []Spindle
3233 var conditions []string
34 var args []any
···59 defer rows.Close()
6061 for rows.Next() {
62- var spindle Spindle
63 var createdAt string
64 var verified sql.NullString
65 var needsUpgrade int
···100}
101102// if there is an existing spindle with the same instance, this returns an error
103-func AddSpindle(e Execer, spindle Spindle) error {
104 _, err := e.Exec(
105 `insert into spindles (owner, instance) values (?, ?)`,
106 spindle.Owner,
···151 return err
152}
153154-func AddSpindleMember(e Execer, member SpindleMember) error {
155 _, err := e.Exec(
156 `insert or ignore into spindle_members (did, rkey, instance, subject) values (?, ?, ?, ?)`,
157 member.Did,
···181 return err
182}
183184-func GetSpindleMembers(e Execer, filters ...filter) ([]SpindleMember, error) {
185- var members []SpindleMember
186187 var conditions []string
188 var args []any
···213 defer rows.Close()
214215 for rows.Next() {
216- var member SpindleMember
217 var createdAt string
218219 if err := rows.Scan(
···6 "strings"
7 "time"
89+ "tangled.org/core/appview/models"
10)
1112+func GetSpindles(e Execer, filters ...filter) ([]models.Spindle, error) {
13+ var spindles []models.Spindle
0000000000000000001415 var conditions []string
16 var args []any
···41 defer rows.Close()
4243 for rows.Next() {
44+ var spindle models.Spindle
45 var createdAt string
46 var verified sql.NullString
47 var needsUpgrade int
···82}
8384// if there is an existing spindle with the same instance, this returns an error
85+func AddSpindle(e Execer, spindle models.Spindle) error {
86 _, err := e.Exec(
87 `insert into spindles (owner, instance) values (?, ?)`,
88 spindle.Owner,
···133 return err
134}
135136+func AddSpindleMember(e Execer, member models.SpindleMember) error {
137 _, err := e.Exec(
138 `insert or ignore into spindle_members (did, rkey, instance, subject) values (?, ?, ?, ?)`,
139 member.Did,
···163 return err
164}
165166+func GetSpindleMembers(e Execer, filters ...filter) ([]models.SpindleMember, error) {
167+ var members []models.SpindleMember
168169 var conditions []string
170 var args []any
···195 defer rows.Close()
196197 for rows.Next() {
198+ var member models.SpindleMember
199 var createdAt string
200201 if err := rows.Scan(
+80-42
appview/db/star.go
···5 "errors"
6 "fmt"
7 "log"
08 "strings"
9 "time"
1011 "github.com/bluesky-social/indigo/atproto/syntax"
012)
1314-type Star struct {
15- StarredByDid string
16- RepoAt syntax.ATURI
17- Created time.Time
18- Rkey string
19-20- // optionally, populate this when querying for reverse mappings
21- Repo *Repo
22-}
23-24-func (star *Star) ResolveRepo(e Execer) error {
25- if star.Repo != nil {
26- return nil
27- }
28-29- repo, err := GetRepoByAtUri(e, star.RepoAt.String())
30- if err != nil {
31- return err
32- }
33-34- star.Repo = repo
35- return nil
36-}
37-38-func AddStar(e Execer, star *Star) error {
39 query := `insert or ignore into stars (starred_by_did, repo_at, rkey) values (?, ?, ?)`
40 _, err := e.Exec(
41 query,
···47}
4849// Get a star record
50-func GetStar(e Execer, starredByDid string, repoAt syntax.ATURI) (*Star, error) {
51 query := `
52 select starred_by_did, repo_at, created, rkey
53 from stars
54 where starred_by_did = ? and repo_at = ?`
55 row := e.QueryRow(query, starredByDid, repoAt)
5657- var star Star
58 var created string
59 err := row.Scan(&star.StarredByDid, &star.RepoAt, &created, &star.Rkey)
60 if err != nil {
···94 return stars, nil
95}
96000000000000000000000000000000000000000000000097func GetStarStatus(e Execer, userDid string, repoAt syntax.ATURI) bool {
98- if _, err := GetStar(e, userDid, repoAt); err != nil {
099 return false
100- } else {
101- return true
102 }
0103}
104105-func GetStars(e Execer, limit int, filters ...filter) ([]Star, error) {
0000106 var conditions []string
107 var args []any
108 for _, filter := range filters {
···134 return nil, err
135 }
136137- starMap := make(map[string][]Star)
138 for rows.Next() {
139- var star Star
140 var created string
141 err := rows.Scan(&star.StarredByDid, &star.RepoAt, &created, &star.Rkey)
142 if err != nil {
···177 }
178 }
179180- var stars []Star
181 for _, s := range starMap {
182 stars = append(stars, s...)
183 }
1840000000000185 return stars, nil
186}
187···209 return count, nil
210}
211212-func GetAllStars(e Execer, limit int) ([]Star, error) {
213- var stars []Star
214215 rows, err := e.Query(`
216 select
···233 defer rows.Close()
234235 for rows.Next() {
236- var star Star
237- var repo Repo
238 var starCreatedAt, repoCreatedAt string
239240 if err := rows.Scan(
···272}
273274// GetTopStarredReposLastWeek returns the top 8 most starred repositories from the last week
275-func GetTopStarredReposLastWeek(e Execer) ([]Repo, error) {
276 // first, get the top repo URIs by star count from the last week
277 query := `
278 with recent_starred_repos as (
···316 }
317318 if len(repoUris) == 0 {
319- return []Repo{}, nil
320 }
321322 // get full repo data
···326 }
327328 // sort repos by the original trending order
329- repoMap := make(map[string]Repo)
330 for _, repo := range repos {
331 repoMap[repo.RepoAt().String()] = repo
332 }
333334- orderedRepos := make([]Repo, 0, len(repoUris))
335 for _, uri := range repoUris {
336 if repo, exists := repoMap[uri]; exists {
337 orderedRepos = append(orderedRepos, repo)
···5 "errors"
6 "fmt"
7 "log"
8+ "slices"
9 "strings"
10 "time"
1112 "github.com/bluesky-social/indigo/atproto/syntax"
13+ "tangled.org/core/appview/models"
14)
1516+func AddStar(e Execer, star *models.Star) error {
00000000000000000000000017 query := `insert or ignore into stars (starred_by_did, repo_at, rkey) values (?, ?, ?)`
18 _, err := e.Exec(
19 query,
···25}
2627// Get a star record
28+func GetStar(e Execer, starredByDid string, repoAt syntax.ATURI) (*models.Star, error) {
29 query := `
30 select starred_by_did, repo_at, created, rkey
31 from stars
32 where starred_by_did = ? and repo_at = ?`
33 row := e.QueryRow(query, starredByDid, repoAt)
3435+ var star models.Star
36 var created string
37 err := row.Scan(&star.StarredByDid, &star.RepoAt, &created, &star.Rkey)
38 if err != nil {
···72 return stars, nil
73}
7475+// getStarStatuses returns a map of repo URIs to star status for a given user
76+// This is an internal helper function to avoid N+1 queries
77+func getStarStatuses(e Execer, userDid string, repoAts []syntax.ATURI) (map[string]bool, error) {
78+ if len(repoAts) == 0 || userDid == "" {
79+ return make(map[string]bool), nil
80+ }
81+82+ placeholders := make([]string, len(repoAts))
83+ args := make([]any, len(repoAts)+1)
84+ args[0] = userDid
85+86+ for i, repoAt := range repoAts {
87+ placeholders[i] = "?"
88+ args[i+1] = repoAt.String()
89+ }
90+91+ query := fmt.Sprintf(`
92+ SELECT repo_at
93+ FROM stars
94+ WHERE starred_by_did = ? AND repo_at IN (%s)
95+ `, strings.Join(placeholders, ","))
96+97+ rows, err := e.Query(query, args...)
98+ if err != nil {
99+ return nil, err
100+ }
101+ defer rows.Close()
102+103+ result := make(map[string]bool)
104+ // Initialize all repos as not starred
105+ for _, repoAt := range repoAts {
106+ result[repoAt.String()] = false
107+ }
108+109+ // Mark starred repos as true
110+ for rows.Next() {
111+ var repoAt string
112+ if err := rows.Scan(&repoAt); err != nil {
113+ return nil, err
114+ }
115+ result[repoAt] = true
116+ }
117+118+ return result, nil
119+}
120+121func GetStarStatus(e Execer, userDid string, repoAt syntax.ATURI) bool {
122+ statuses, err := getStarStatuses(e, userDid, []syntax.ATURI{repoAt})
123+ if err != nil {
124 return false
00125 }
126+ return statuses[repoAt.String()]
127}
128129+// GetStarStatuses returns a map of repo URIs to star status for a given user
130+func GetStarStatuses(e Execer, userDid string, repoAts []syntax.ATURI) (map[string]bool, error) {
131+ return getStarStatuses(e, userDid, repoAts)
132+}
133+func GetStars(e Execer, limit int, filters ...filter) ([]models.Star, error) {
134 var conditions []string
135 var args []any
136 for _, filter := range filters {
···162 return nil, err
163 }
164165+ starMap := make(map[string][]models.Star)
166 for rows.Next() {
167+ var star models.Star
168 var created string
169 err := rows.Scan(&star.StarredByDid, &star.RepoAt, &created, &star.Rkey)
170 if err != nil {
···205 }
206 }
207208+ var stars []models.Star
209 for _, s := range starMap {
210 stars = append(stars, s...)
211 }
212213+ slices.SortFunc(stars, func(a, b models.Star) int {
214+ if a.Created.After(b.Created) {
215+ return -1
216+ }
217+ if b.Created.After(a.Created) {
218+ return 1
219+ }
220+ return 0
221+ })
222+223 return stars, nil
224}
225···247 return count, nil
248}
249250+func GetAllStars(e Execer, limit int) ([]models.Star, error) {
251+ var stars []models.Star
252253 rows, err := e.Query(`
254 select
···271 defer rows.Close()
272273 for rows.Next() {
274+ var star models.Star
275+ var repo models.Repo
276 var starCreatedAt, repoCreatedAt string
277278 if err := rows.Scan(
···310}
311312// GetTopStarredReposLastWeek returns the top 8 most starred repositories from the last week
313+func GetTopStarredReposLastWeek(e Execer) ([]models.Repo, error) {
314 // first, get the top repo URIs by star count from the last week
315 query := `
316 with recent_starred_repos as (
···354 }
355356 if len(repoUris) == 0 {
357+ return []models.Repo{}, nil
358 }
359360 // get full repo data
···364 }
365366 // sort repos by the original trending order
367+ repoMap := make(map[string]models.Repo)
368 for _, repo := range repos {
369 repoMap[repo.RepoAt().String()] = repo
370 }
371372+ orderedRepos := make([]models.Repo, 0, len(repoUris))
373 for _, uri := range repoUris {
374 if repo, exists := repoMap[uri]; exists {
375 orderedRepos = append(orderedRepos, repo)
+5-110
appview/db/strings.go
···1package db
23import (
4- "bytes"
5 "database/sql"
6 "errors"
7 "fmt"
8- "io"
9 "strings"
10 "time"
11- "unicode/utf8"
1213- "github.com/bluesky-social/indigo/atproto/syntax"
14- "tangled.sh/tangled.sh/core/api/tangled"
15)
1617-type String struct {
18- Did syntax.DID
19- Rkey string
20-21- Filename string
22- Description string
23- Contents string
24- Created time.Time
25- Edited *time.Time
26-}
27-28-func (s *String) StringAt() syntax.ATURI {
29- return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", s.Did, tangled.StringNSID, s.Rkey))
30-}
31-32-type StringStats struct {
33- LineCount uint64
34- ByteCount uint64
35-}
36-37-func (s String) Stats() StringStats {
38- lineCount, err := countLines(strings.NewReader(s.Contents))
39- if err != nil {
40- // non-fatal
41- // TODO: log this?
42- }
43-44- return StringStats{
45- LineCount: uint64(lineCount),
46- ByteCount: uint64(len(s.Contents)),
47- }
48-}
49-50-func (s String) Validate() error {
51- var err error
52-53- if utf8.RuneCountInString(s.Filename) > 140 {
54- err = errors.Join(err, fmt.Errorf("filename too long"))
55- }
56-57- if utf8.RuneCountInString(s.Description) > 280 {
58- err = errors.Join(err, fmt.Errorf("description too long"))
59- }
60-61- if len(s.Contents) == 0 {
62- err = errors.Join(err, fmt.Errorf("contents is empty"))
63- }
64-65- return err
66-}
67-68-func (s *String) AsRecord() tangled.String {
69- return tangled.String{
70- Filename: s.Filename,
71- Description: s.Description,
72- Contents: s.Contents,
73- CreatedAt: s.Created.Format(time.RFC3339),
74- }
75-}
76-77-func StringFromRecord(did, rkey string, record tangled.String) String {
78- created, err := time.Parse(record.CreatedAt, time.RFC3339)
79- if err != nil {
80- created = time.Now()
81- }
82- return String{
83- Did: syntax.DID(did),
84- Rkey: rkey,
85- Filename: record.Filename,
86- Description: record.Description,
87- Contents: record.Contents,
88- Created: created,
89- }
90-}
91-92-func AddString(e Execer, s String) error {
93 _, err := e.Exec(
94 `insert into strings (
95 did,
···123 return err
124}
125126-func GetStrings(e Execer, limit int, filters ...filter) ([]String, error) {
127- var all []String
128129 var conditions []string
130 var args []any
···167 defer rows.Close()
168169 for rows.Next() {
170- var s String
171 var createdAt string
172 var editedAt sql.NullString
173···248 _, err := e.Exec(query, args...)
249 return err
250}
251-252-func countLines(r io.Reader) (int, error) {
253- buf := make([]byte, 32*1024)
254- bufLen := 0
255- count := 0
256- nl := []byte{'\n'}
257-258- for {
259- c, err := r.Read(buf)
260- if c > 0 {
261- bufLen += c
262- }
263- count += bytes.Count(buf[:c], nl)
264-265- switch {
266- case err == io.EOF:
267- /* handle last line not having a newline at the end */
268- if bufLen >= 1 && buf[(bufLen-1)%(32*1024)] != '\n' {
269- count++
270- }
271- return count, nil
272- case err != nil:
273- return 0, err
274- }
275- }
276-}
···1package db
23import (
04 "database/sql"
5 "errors"
6 "fmt"
07 "strings"
8 "time"
0910+ "tangled.org/core/appview/models"
011)
1213+func AddString(e Execer, s models.String) error {
00000000000000000000000000000000000000000000000000000000000000000000000000014 _, err := e.Exec(
15 `insert into strings (
16 did,
···44 return err
45}
4647+func GetStrings(e Execer, limit int, filters ...filter) ([]models.String, error) {
48+ var all []models.String
4950 var conditions []string
51 var args []any
···88 defer rows.Close()
8990 for rows.Next() {
91+ var s models.String
92 var createdAt string
93 var editedAt sql.NullString
94···169 _, err := e.Exec(query, args...)
170 return err
171}
00000000000000000000000000
+93-42
appview/db/timeline.go
···23import (
4 "sort"
5- "time"
6-)
78-type TimelineEvent struct {
9- *Repo
10- *Follow
11- *Star
12-13- EventAt time.Time
14-15- // optional: populate only if Repo is a fork
16- Source *Repo
17-18- // optional: populate only if event is Follow
19- *Profile
20- *FollowStats
21-}
2223// TODO: this gathers heterogenous events from different sources and aggregates
24// them in code; if we did this entirely in sql, we could order and limit and paginate easily
25-func MakeTimeline(e Execer, limit int) ([]TimelineEvent, error) {
26- var events []TimelineEvent
2728- repos, err := getTimelineRepos(e, limit)
29 if err != nil {
30 return nil, err
31 }
3233- stars, err := getTimelineStars(e, limit)
34 if err != nil {
35 return nil, err
36 }
3738- follows, err := getTimelineFollows(e, limit)
39 if err != nil {
40 return nil, err
41 }
···56 return events, nil
57}
5859-func getTimelineRepos(e Execer, limit int) ([]TimelineEvent, error) {
00000000000000000000000000060 repos, err := GetRepos(e, limit)
61 if err != nil {
62 return nil, err
···70 }
71 }
7273- var origRepos []Repo
74 if args != nil {
75 origRepos, err = GetRepos(e, 0, FilterIn("at_uri", args))
76 }
···78 return nil, err
79 }
8081- uriToRepo := make(map[string]Repo)
82 for _, r := range origRepos {
83 uriToRepo[r.RepoAt().String()] = r
84 }
8586- var events []TimelineEvent
0000087 for _, r := range repos {
88- var source *Repo
89 if r.Source != "" {
90 if origRepo, ok := uriToRepo[r.Source]; ok {
91 source = &origRepo
92 }
93 }
9495- events = append(events, TimelineEvent{
96- Repo: &r,
97- EventAt: r.Created,
98- Source: source,
000099 })
100 }
101102 return events, nil
103}
104105-func getTimelineStars(e Execer, limit int) ([]TimelineEvent, error) {
106 stars, err := GetStars(e, limit)
107 if err != nil {
108 return nil, err
···118 }
119 stars = stars[:n]
120121- var events []TimelineEvent
0000000000122 for _, s := range stars {
123- events = append(events, TimelineEvent{
124- Star: &s,
125- EventAt: s.Created,
0000126 })
127 }
128129 return events, nil
130}
131132-func getTimelineFollows(e Execer, limit int) ([]TimelineEvent, error) {
133 follows, err := GetFollows(e, limit)
134 if err != nil {
135 return nil, err
···154 return nil, err
155 }
156157- var events []TimelineEvent
00000000158 for _, f := range follows {
159 profile, _ := profiles[f.SubjectDid]
160 followStatMap, _ := followStatMap[f.SubjectDid]
161162- events = append(events, TimelineEvent{
163- Follow: &f,
164- Profile: profile,
165- FollowStats: &followStatMap,
166- EventAt: f.FollowedAt,
000000167 })
168 }
169
···23import (
4 "sort"
0056+ "github.com/bluesky-social/indigo/atproto/syntax"
7+ "tangled.org/core/appview/models"
8+)
00000000000910// TODO: this gathers heterogenous events from different sources and aggregates
11// them in code; if we did this entirely in sql, we could order and limit and paginate easily
12+func MakeTimeline(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) {
13+ var events []models.TimelineEvent
1415+ repos, err := getTimelineRepos(e, limit, loggedInUserDid)
16 if err != nil {
17 return nil, err
18 }
1920+ stars, err := getTimelineStars(e, limit, loggedInUserDid)
21 if err != nil {
22 return nil, err
23 }
2425+ follows, err := getTimelineFollows(e, limit, loggedInUserDid)
26 if err != nil {
27 return nil, err
28 }
···43 return events, nil
44}
4546+func fetchStarStatuses(e Execer, loggedInUserDid string, repos []models.Repo) (map[string]bool, error) {
47+ if loggedInUserDid == "" {
48+ return nil, nil
49+ }
50+51+ var repoAts []syntax.ATURI
52+ for _, r := range repos {
53+ repoAts = append(repoAts, r.RepoAt())
54+ }
55+56+ return GetStarStatuses(e, loggedInUserDid, repoAts)
57+}
58+59+func getRepoStarInfo(repo *models.Repo, starStatuses map[string]bool) (bool, int64) {
60+ var isStarred bool
61+ if starStatuses != nil {
62+ isStarred = starStatuses[repo.RepoAt().String()]
63+ }
64+65+ var starCount int64
66+ if repo.RepoStats != nil {
67+ starCount = int64(repo.RepoStats.StarCount)
68+ }
69+70+ return isStarred, starCount
71+}
72+73+func getTimelineRepos(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) {
74 repos, err := GetRepos(e, limit)
75 if err != nil {
76 return nil, err
···84 }
85 }
8687+ var origRepos []models.Repo
88 if args != nil {
89 origRepos, err = GetRepos(e, 0, FilterIn("at_uri", args))
90 }
···92 return nil, err
93 }
9495+ uriToRepo := make(map[string]models.Repo)
96 for _, r := range origRepos {
97 uriToRepo[r.RepoAt().String()] = r
98 }
99100+ starStatuses, err := fetchStarStatuses(e, loggedInUserDid, repos)
101+ if err != nil {
102+ return nil, err
103+ }
104+105+ var events []models.TimelineEvent
106 for _, r := range repos {
107+ var source *models.Repo
108 if r.Source != "" {
109 if origRepo, ok := uriToRepo[r.Source]; ok {
110 source = &origRepo
111 }
112 }
113114+ isStarred, starCount := getRepoStarInfo(&r, starStatuses)
115+116+ events = append(events, models.TimelineEvent{
117+ Repo: &r,
118+ EventAt: r.Created,
119+ Source: source,
120+ IsStarred: isStarred,
121+ StarCount: starCount,
122 })
123 }
124125 return events, nil
126}
127128+func getTimelineStars(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) {
129 stars, err := GetStars(e, limit)
130 if err != nil {
131 return nil, err
···141 }
142 stars = stars[:n]
143144+ var repos []models.Repo
145+ for _, s := range stars {
146+ repos = append(repos, *s.Repo)
147+ }
148+149+ starStatuses, err := fetchStarStatuses(e, loggedInUserDid, repos)
150+ if err != nil {
151+ return nil, err
152+ }
153+154+ var events []models.TimelineEvent
155 for _, s := range stars {
156+ isStarred, starCount := getRepoStarInfo(s.Repo, starStatuses)
157+158+ events = append(events, models.TimelineEvent{
159+ Star: &s,
160+ EventAt: s.Created,
161+ IsStarred: isStarred,
162+ StarCount: starCount,
163 })
164 }
165166 return events, nil
167}
168169+func getTimelineFollows(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) {
170 follows, err := GetFollows(e, limit)
171 if err != nil {
172 return nil, err
···191 return nil, err
192 }
193194+ var followStatuses map[string]models.FollowStatus
195+ if loggedInUserDid != "" {
196+ followStatuses, err = GetFollowStatuses(e, loggedInUserDid, subjects)
197+ if err != nil {
198+ return nil, err
199+ }
200+ }
201+202+ var events []models.TimelineEvent
203 for _, f := range follows {
204 profile, _ := profiles[f.SubjectDid]
205 followStatMap, _ := followStatMap[f.SubjectDid]
206207+ followStatus := models.IsNotFollowing
208+ if followStatuses != nil {
209+ followStatus = followStatuses[f.SubjectDid]
210+ }
211+212+ events = append(events, models.TimelineEvent{
213+ Follow: &f,
214+ Profile: profile,
215+ FollowStats: &followStatMap,
216+ FollowStatus: &followStatus,
217+ EventAt: f.FollowedAt,
218 })
219 }
220
···1+package models
2+3+import (
4+ "time"
5+6+ "github.com/bluesky-social/indigo/atproto/syntax"
7+)
8+9+type Spindle struct {
10+ Id int
11+ Owner syntax.DID
12+ Instance string
13+ Verified *time.Time
14+ Created time.Time
15+ NeedsUpgrade bool
16+}
17+18+type SpindleMember struct {
19+ Id int
20+ Did syntax.DID // owner of the record
21+ Rkey string // rkey of the record
22+ Instance string
23+ Subject syntax.DID // the member being added
24+ Created time.Time
25+}
+17
appview/models/star.go
···00000000000000000
···1+package models
2+3+import (
4+ "time"
5+6+ "github.com/bluesky-social/indigo/atproto/syntax"
7+)
8+9+type Star struct {
10+ StarredByDid string
11+ RepoAt syntax.ATURI
12+ Created time.Time
13+ Rkey string
14+15+ // optionally, populate this when querying for reverse mappings
16+ Repo *Repo
17+}
···1+**Last updated:** September 26, 2025
2+3+This Privacy Policy describes how Tangled ("we," "us," or "our")
4+collects, uses, and shares your personal information when you use our
5+platform and services (the "Service").
6+7+## 1. Information We Collect
8+9+### Account Information
10+11+When you create an account, we collect:
12+13+- Your chosen username
14+- Email address
15+- Profile information you choose to provide
16+- Authentication data
17+18+### Content and Activity
19+20+We store:
21+22+- Code repositories and associated metadata
23+- Issues, pull requests, and comments
24+- Activity logs and usage patterns
25+- Public keys for authentication
26+27+## 2. Data Location and Hosting
28+29+### EU Data Hosting
30+31+**All Tangled service data is hosted within the European Union.**
32+Specifically:
33+34+- **Personal Data Servers (PDS):** Accounts hosted on Tangled PDS
35+ (*.tngl.sh) are located in Finland
36+- **Application Data:** All other service data is stored on EU-based
37+ servers
38+- **Data Processing:** All data processing occurs within EU
39+ jurisdiction
40+41+### External PDS Notice
42+43+**Important:** If your account is hosted on Bluesky's PDS or other
44+self-hosted Personal Data Servers (not *.tngl.sh), we do not control
45+that data. The data protection, storage location, and privacy
46+practices for such accounts are governed by the respective PDS
47+provider's policies, not this Privacy Policy. We only control data
48+processing within our own services and infrastructure.
49+50+## 3. Third-Party Data Processors
51+52+We only share your data with the following third-party processors:
53+54+### Resend (Email Services)
55+56+- **Purpose:** Sending transactional emails (account verification,
57+ notifications)
58+- **Data Shared:** Email address and necessary message content
59+60+### Cloudflare (Image Caching)
61+62+- **Purpose:** Caching and optimizing image delivery
63+- **Data Shared:** Public images and associated metadata for caching
64+ purposes
65+66+### Posthog (Usage Metrics Tracking)
67+68+- **Purpose:** Tracking usage and platform metrics
69+- **Data Shared:** Anonymous usage data, IP addresses, DIDs, and browser
70+ information
71+72+## 4. How We Use Your Information
73+74+We use your information to:
75+76+- Provide and maintain the Service
77+- Process your transactions and requests
78+- Send you technical notices and support messages
79+- Improve and develop new features
80+- Ensure security and prevent fraud
81+- Comply with legal obligations
82+83+## 5. Data Sharing and Disclosure
84+85+We do not sell, trade, or rent your personal information. We may share
86+your information only in the following circumstances:
87+88+- With the third-party processors listed above
89+- When required by law or legal process
90+- To protect our rights, property, or safety, or that of our users
91+- In connection with a merger, acquisition, or sale of assets (with
92+ appropriate protections)
93+94+## 6. Data Security
95+96+We implement appropriate technical and organizational measures to
97+protect your personal information against unauthorized access,
98+alteration, disclosure, or destruction. However, no method of
99+transmission over the Internet is 100% secure.
100+101+## 7. Data Retention
102+103+We retain your personal information for as long as necessary to provide
104+the Service and fulfill the purposes outlined in this Privacy Policy,
105+unless a longer retention period is required by law.
106+107+## 8. Your Rights
108+109+Under applicable data protection laws, you have the right to:
110+111+- Access your personal information
112+- Correct inaccurate information
113+- Request deletion of your information
114+- Object to processing of your information
115+- Data portability
116+- Withdraw consent (where applicable)
117+118+## 9. Cookies and Tracking
119+120+We use cookies and similar technologies to:
121+122+- Maintain your login session
123+- Remember your preferences
124+- Analyze usage patterns to improve the Service
125+126+You can control cookie settings through your browser preferences.
127+128+## 10. Children's Privacy
129+130+The Service is not intended for children under 16 years of age. We do
131+not knowingly collect personal information from children under 16. If
132+we become aware that we have collected such information, we will take
133+steps to delete it.
134+135+## 11. International Data Transfers
136+137+While all our primary data processing occurs within the EU, some of our
138+third-party processors may process data outside the EU. When this
139+occurs, we ensure appropriate safeguards are in place, such as Standard
140+Contractual Clauses or adequacy decisions.
141+142+## 12. Changes to This Privacy Policy
143+144+We may update this Privacy Policy from time to time. We will notify you
145+of any changes by posting the new Privacy Policy on this page and
146+updating the "Last updated" date.
147+148+## 13. Contact Information
149+150+If you have any questions about this Privacy Policy or wish to exercise
151+your rights, please contact us through our platform or via email.
152+153+---
154+155+This Privacy Policy complies with the EU General Data Protection
156+Regulation (GDPR) and other applicable data protection laws.
···1+**Last updated:** September 26, 2025
2+3+Welcome to Tangled. These Terms of Service ("Terms") govern your access
4+to and use of the Tangled platform and services (the "Service")
5+operated by us ("Tangled," "we," "us," or "our").
6+7+## 1. Acceptance of Terms
8+9+By accessing or using our Service, you agree to be bound by these Terms.
10+If you disagree with any part of these terms, then you may not access
11+the Service.
12+13+## 2. Account Registration
14+15+To use certain features of the Service, you must register for an
16+account. You agree to provide accurate, current, and complete
17+information during the registration process and to update such
18+information to keep it accurate, current, and complete.
19+20+## 3. Account Termination
21+22+> **Important Notice**
23+>
24+> **We reserve the right to terminate, suspend, or restrict access to
25+> your account at any time, for any reason, or for no reason at all, at
26+> our sole discretion.** This includes, but is not limited to,
27+> termination for violation of these Terms, inappropriate conduct, spam,
28+> abuse, or any other behavior we deem harmful to the Service or other
29+> users.
30+>
31+> Account termination may result in the loss of access to your
32+> repositories, data, and other content associated with your account. We
33+> are not obligated to provide advance notice of termination, though we
34+> may do so in our discretion.
35+36+## 4. Acceptable Use
37+38+You agree not to use the Service to:
39+40+- Violate any applicable laws or regulations
41+- Infringe upon the rights of others
42+- Upload, store, or share content that is illegal, harmful, threatening,
43+ abusive, harassing, defamatory, vulgar, obscene, or otherwise
44+ objectionable
45+- Engage in spam, phishing, or other deceptive practices
46+- Attempt to gain unauthorized access to the Service or other users'
47+ accounts
48+- Interfere with or disrupt the Service or servers connected to the
49+ Service
50+51+## 5. Content and Intellectual Property
52+53+You retain ownership of the content you upload to the Service. By
54+uploading content, you grant us a non-exclusive, worldwide, royalty-free
55+license to use, reproduce, modify, and distribute your content as
56+necessary to provide the Service.
57+58+## 6. Privacy
59+60+Your privacy is important to us. Please review our [Privacy
61+Policy](/privacy), which also governs your use of the Service.
62+63+## 7. Disclaimers
64+65+The Service is provided on an "AS IS" and "AS AVAILABLE" basis. We make
66+no warranties, expressed or implied, and hereby disclaim and negate all
67+other warranties including without limitation, implied warranties or
68+conditions of merchantability, fitness for a particular purpose, or
69+non-infringement of intellectual property or other violation of rights.
70+71+## 8. Limitation of Liability
72+73+In no event shall Tangled, nor its directors, employees, partners,
74+agents, suppliers, or affiliates, be liable for any indirect,
75+incidental, special, consequential, or punitive damages, including
76+without limitation, loss of profits, data, use, goodwill, or other
77+intangible losses, resulting from your use of the Service.
78+79+## 9. Indemnification
80+81+You agree to defend, indemnify, and hold harmless Tangled and its
82+affiliates, officers, directors, employees, and agents from and against
83+any and all claims, damages, obligations, losses, liabilities, costs,
84+or debt, and expenses (including attorney's fees).
85+86+## 10. Governing Law
87+88+These Terms shall be interpreted and governed by the laws of Finland,
89+without regard to its conflict of law provisions.
90+91+## 11. Changes to Terms
92+93+We reserve the right to modify or replace these Terms at any time. If a
94+revision is material, we will try to provide at least 30 days notice
95+prior to any new terms taking effect.
96+97+## 12. Contact Information
98+99+If you have any questions about these Terms of Service, please contact
100+us through our platform or via email.
101+102+---
103+104+These terms are effective as of the last updated date shown above and
105+will remain in effect except with respect to any changes in their
106+provisions in the future, which will be in effect immediately after
107+being posted on this page.
+15-17
appview/pages/markup/format.go
···1package markup
23-import "strings"
0045type Format string
6···10)
1112var FileTypes map[Format][]string = map[Format][]string{
13- FormatMarkdown: []string{".md", ".markdown", ".mdown", ".mkdn", ".mkd"},
14}
1516-// ReadmeFilenames contains the list of common README filenames to search for,
17-// in order of preference. Only includes well-supported formats.
18-var ReadmeFilenames = []string{
19- "README.md", "readme.md",
20- "README",
21- "readme",
22- "README.markdown",
23- "readme.markdown",
24- "README.txt",
25- "readme.txt",
26}
2728func GetFormat(filename string) Format {
29- for format, extensions := range FileTypes {
30- for _, extension := range extensions {
31- if strings.HasSuffix(filename, extension) {
32- return format
33- }
34 }
35 }
36 // default format
···1package markup
23+import (
4+ "regexp"
5+)
67type Format string
8···12)
1314var FileTypes map[Format][]string = map[Format][]string{
15+ FormatMarkdown: {".md", ".markdown", ".mdown", ".mkdn", ".mkd"},
16}
1718+var FileTypePatterns = map[Format]*regexp.Regexp{
19+ FormatMarkdown: regexp.MustCompile(`(?i)\.(md|markdown|mdown|mkdn|mkd)$`),
20+}
21+22+var ReadmePattern = regexp.MustCompile(`(?i)^readme(\.(md|markdown|txt))?$`)
23+24+func IsReadmeFile(filename string) bool {
25+ return ReadmePattern.MatchString(filename)
0026}
2728func GetFormat(filename string) Format {
29+ for format, pattern := range FileTypePatterns {
30+ if pattern.MatchString(filename) {
31+ return format
0032 }
33 }
34 // default format
+2-2
appview/pages/markup/markdown.go
···22 "github.com/yuin/goldmark/util"
23 htmlparse "golang.org/x/net/html"
2425- "tangled.sh/tangled.sh/core/api/tangled"
26- "tangled.sh/tangled.sh/core/appview/pages/repoinfo"
27)
2829// RendererType defines the type of renderer to use based on context
···22 "github.com/yuin/goldmark/util"
23 htmlparse "golang.org/x/net/html"
2425+ "tangled.org/core/api/tangled"
26+ "tangled.org/core/appview/pages/repoinfo"
27)
2829// RendererType defines the type of renderer to use based on context
···30 <div class="mx-6">
31 These services may not be fully accessible until upgraded.
32 <a class="underline text-red-800 dark:text-red-200"
33- href="https://tangled.sh/@tangled.sh/core/tree/master/docs/migrations.md">
34 Click to read the upgrade guide</a>.
35 </div>
36 </details>
···30 <div class="mx-6">
31 These services may not be fully accessible until upgraded.
32 <a class="underline text-red-800 dark:text-red-200"
33+ href="https://tangled.org/@tangled.org/core/tree/master/docs/migrations.md">
34 Click to read the upgrade guide</a>.
35 </div>
36 </details>
···22 <p class="text-gray-500 dark:text-gray-400">
23 Choose a spindle to execute your workflows on. Only repository owners
24 can configure spindles. Spindles can be selfhosted,
25- <a class="text-gray-500 dark:text-gray-400 underline" href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md">
26 click to learn more.
27 </a>
28 </p>
···109 hx-swap="none"
110 class="flex flex-col gap-2"
111>
112- <p class="uppercase p-0">ADD SECRET</p>
113 <p class="text-sm text-gray-500 dark:text-gray-400">Secrets are available as environment variables in the workflow.</p>
114 <input
115 type="text"
···22 <p class="text-gray-500 dark:text-gray-400">
23 Choose a spindle to execute your workflows on. Only repository owners
24 can configure spindles. Spindles can be selfhosted,
25+ <a class="text-gray-500 dark:text-gray-400 underline" href="https://tangled.org/@tangled.org/core/blob/master/docs/spindle/hosting.md">
26 click to learn more.
27 </a>
28 </p>
···109 hx-swap="none"
110 class="flex flex-col gap-2"
111>
112+ <p class="uppercase p-0 font-bold">ADD SECRET</p>
113 <p class="text-sm text-gray-500 dark:text-gray-400">Secrets are available as environment variables in the workflow.</p>
114 <input
115 type="text"
···19First, clone this repository:
2021```
22-git clone https://tangled.sh/@tangled.sh/core
23```
2425Then, build the `knot` CLI. This is the knot administration and operation tool.
···130131You should now have a running knot server! You can finalize
132your registration by hitting the `verify` button on the
133-[/knots](https://tangled.sh/knots) page. This simply creates
134a record on your PDS to announce the existence of the knot.
135136### custom paths
···19First, clone this repository:
2021```
22+git clone https://tangled.org/@tangled.org/core
23```
2425Then, build the `knot` CLI. This is the knot administration and operation tool.
···130131You should now have a running knot server! You can finalize
132your registration by hitting the `verify` button on the
133+[/knots](https://tangled.org/knots) page. This simply creates
134a record on your PDS to announce the existence of the knot.
135136### custom paths
+4-5
docs/migrations.md
···14For knots:
1516- Upgrade to latest tag (v1.9.0 or above)
17-- Head to the [knot dashboard](https://tangled.sh/knots) and
18 hit the "retry" button to verify your knot
1920For spindles:
2122- Upgrade to latest tag (v1.9.0 or above)
23- Head to the [spindle
24- dashboard](https://tangled.sh/spindles) and hit the
25 "retry" button to verify your spindle
2627## Upgrading from v1.7.x
···38 environment variable entirely
39- `KNOT_SERVER_OWNER` is now required on boot, set this to
40 your DID. You can find your DID in the
41- [settings](https://tangled.sh/settings) page.
42- Restart your knot once you have replaced the environment
43 variable
44-- Head to the [knot dashboard](https://tangled.sh/knots) and
45 hit the "retry" button to verify your knot. This simply
46 writes a `sh.tangled.knot` record to your PDS.
47···57 };
58 };
59```
60-
···14For knots:
1516- Upgrade to latest tag (v1.9.0 or above)
17+- Head to the [knot dashboard](https://tangled.org/knots) and
18 hit the "retry" button to verify your knot
1920For spindles:
2122- Upgrade to latest tag (v1.9.0 or above)
23- Head to the [spindle
24+ dashboard](https://tangled.org/spindles) and hit the
25 "retry" button to verify your spindle
2627## Upgrading from v1.7.x
···38 environment variable entirely
39- `KNOT_SERVER_OWNER` is now required on boot, set this to
40 your DID. You can find your DID in the
41+ [settings](https://tangled.org/settings) page.
42- Restart your knot once you have replaced the environment
43 variable
44+- Head to the [knot dashboard](https://tangled.org/knots) and
45 hit the "retry" button to verify your knot. This simply
46 writes a `sh.tangled.knot` record to your PDS.
47···57 };
58 };
59```
0
+1-1
docs/spindle/openbao.md
···44### production
4546You would typically use a systemd service with a configuration file. Refer to
47-[@tangled.sh/infra](https://tangled.sh/@tangled.sh/infra) for how this can be
48achieved using Nix.
4950Then, initialize the bao server:
···44### production
4546You would typically use a systemd service with a configuration file. Refer to
47+[@tangled.org/infra](https://tangled.org/@tangled.org/infra) for how this can be
48achieved using Nix.
4950Then, initialize the bao server:
+3-3
docs/spindle/pipeline.md
···21 - `manual`: The workflow can be triggered manually.
22- `branch`: This is a **required** field that defines which branches the workflow should run for. If used with the `push` event, commits to the branch(es) listed here will trigger the workflow. If used with the `pull_request` event, updates to pull requests targeting the branch(es) listed here will trigger the workflow. This field has no effect with the `manual` event.
2324-For example, if you'd like define a workflow that runs when commits are pushed to the `main` and `develop` branches, or when pull requests that target the `main` branch are updated, or manually, you can do so with:
2526```yaml
27when:
···73 - nodejs
74 - go
75 # custom registry
76- git+https://tangled.sh/@example.com/my_pkg:
77 - my_pkg
78```
79···141 - nodejs
142 - go
143 # custom registry
144- git+https://tangled.sh/@example.com/my_pkg:
145 - my_pkg
146147environment:
···21 - `manual`: The workflow can be triggered manually.
22- `branch`: This is a **required** field that defines which branches the workflow should run for. If used with the `push` event, commits to the branch(es) listed here will trigger the workflow. If used with the `pull_request` event, updates to pull requests targeting the branch(es) listed here will trigger the workflow. This field has no effect with the `manual` event.
2324+For example, if you'd like to define a workflow that runs when commits are pushed to the `main` and `develop` branches, or when pull requests that target the `main` branch are updated, or manually, you can do so with:
2526```yaml
27when:
···73 - nodejs
74 - go
75 # custom registry
76+ git+https://tangled.org/@example.com/my_pkg:
77 - my_pkg
78```
79···141 - nodejs
142 - go
143 # custom registry
144+ git+https://tangled.org/@example.com/my_pkg:
145 - my_pkg
146147environment:
···5 "net/http"
6 "runtime/debug"
78- "tangled.sh/tangled.sh/core/api/tangled"
9)
1011// version is set during build time.
···24 var modified bool
2526 for _, mod := range info.Deps {
27- if mod.Path == "tangled.sh/tangled.sh/knotserver/xrpc" {
28 modVer = mod.Version
29 break
30 }
···5 "net/http"
6 "runtime/debug"
78+ "tangled.org/core/api/tangled"
9)
1011// version is set during build time.
···24 var modified bool
2526 for _, mod := range info.Deps {
27+ if mod.Path == "tangled.org/tangled.org/knotserver/xrpc" {
28 modVer = mod.Version
29 break
30 }
···1-# Privacy Policy
2-3-**Last updated:** January 15, 2025
4-5-This Privacy Policy describes how Tangled ("we," "us," or "our")
6-collects, uses, and shares your personal information when you use our
7-platform and services (the "Service").
8-9-## 1. Information We Collect
10-11-### Account Information
12-13-When you create an account, we collect:
14-15-- Your chosen username
16-- Email address
17-- Profile information you choose to provide
18-- Authentication data
19-20-### Content and Activity
21-22-We store:
23-24-- Code repositories and associated metadata
25-- Issues, pull requests, and comments
26-- Activity logs and usage patterns
27-- Public keys for authentication
28-29-## 2. Data Location and Hosting
30-31-### EU Data Hosting
32-33-**All Tangled service data is hosted within the European Union.**
34-Specifically:
35-36-- **Personal Data Servers (PDS):** Accounts hosted on Tangled PDS
37- (*.tngl.sh) are located in Finland
38-- **Application Data:** All other service data is stored on EU-based
39- servers
40-- **Data Processing:** All data processing occurs within EU
41- jurisdiction
42-43-### External PDS Notice
44-45-**Important:** If your account is hosted on Bluesky's PDS or other
46-self-hosted Personal Data Servers (not *.tngl.sh), we do not control
47-that data. The data protection, storage location, and privacy
48-practices for such accounts are governed by the respective PDS
49-provider's policies, not this Privacy Policy. We only control data
50-processing within our own services and infrastructure.
51-52-## 3. Third-Party Data Processors
53-54-We only share your data with the following third-party processors:
55-56-### Resend (Email Services)
57-58-- **Purpose:** Sending transactional emails (account verification,
59- notifications)
60-- **Data Shared:** Email address and necessary message content
61-62-### Cloudflare (Image Caching)
63-64-- **Purpose:** Caching and optimizing image delivery
65-- **Data Shared:** Public images and associated metadata for caching
66- purposes
67-68-### Posthog (Usage Metrics Tracking)
69-70-- **Purpose:** Tracking usage and platform metrics
71-- **Data Shared:** Anonymous usage data, IP addresses, DIDs, and browser
72- information
73-74-## 4. How We Use Your Information
75-76-We use your information to:
77-78-- Provide and maintain the Service
79-- Process your transactions and requests
80-- Send you technical notices and support messages
81-- Improve and develop new features
82-- Ensure security and prevent fraud
83-- Comply with legal obligations
84-85-## 5. Data Sharing and Disclosure
86-87-We do not sell, trade, or rent your personal information. We may share
88-your information only in the following circumstances:
89-90-- With the third-party processors listed above
91-- When required by law or legal process
92-- To protect our rights, property, or safety, or that of our users
93-- In connection with a merger, acquisition, or sale of assets (with
94- appropriate protections)
95-96-## 6. Data Security
97-98-We implement appropriate technical and organizational measures to
99-protect your personal information against unauthorized access,
100-alteration, disclosure, or destruction. However, no method of
101-transmission over the Internet is 100% secure.
102-103-## 7. Data Retention
104-105-We retain your personal information for as long as necessary to provide
106-the Service and fulfill the purposes outlined in this Privacy Policy,
107-unless a longer retention period is required by law.
108-109-## 8. Your Rights
110-111-Under applicable data protection laws, you have the right to:
112-113-- Access your personal information
114-- Correct inaccurate information
115-- Request deletion of your information
116-- Object to processing of your information
117-- Data portability
118-- Withdraw consent (where applicable)
119-120-## 9. Cookies and Tracking
121-122-We use cookies and similar technologies to:
123-124-- Maintain your login session
125-- Remember your preferences
126-- Analyze usage patterns to improve the Service
127-128-You can control cookie settings through your browser preferences.
129-130-## 10. Children's Privacy
131-132-The Service is not intended for children under 16 years of age. We do
133-not knowingly collect personal information from children under 16. If
134-we become aware that we have collected such information, we will take
135-steps to delete it.
136-137-## 11. International Data Transfers
138-139-While all our primary data processing occurs within the EU, some of our
140-third-party processors may process data outside the EU. When this
141-occurs, we ensure appropriate safeguards are in place, such as Standard
142-Contractual Clauses or adequacy decisions.
143-144-## 12. Changes to This Privacy Policy
145-146-We may update this Privacy Policy from time to time. We will notify you
147-of any changes by posting the new Privacy Policy on this page and
148-updating the "Last updated" date.
149-150-## 13. Contact Information
151-152-If you have any questions about this Privacy Policy or wish to exercise
153-your rights, please contact us through our platform or via email.
154-155----
156-157-This Privacy Policy complies with the EU General Data Protection
158-Regulation (GDPR) and other applicable data protection laws.
···1-# Terms of Service
2-3-**Last updated:** January 15, 2025
4-5-Welcome to Tangled. These Terms of Service ("Terms") govern your access
6-to and use of the Tangled platform and services (the "Service")
7-operated by us ("Tangled," "we," "us," or "our").
8-9-## 1. Acceptance of Terms
10-11-By accessing or using our Service, you agree to be bound by these Terms.
12-If you disagree with any part of these terms, then you may not access
13-the Service.
14-15-## 2. Account Registration
16-17-To use certain features of the Service, you must register for an
18-account. You agree to provide accurate, current, and complete
19-information during the registration process and to update such
20-information to keep it accurate, current, and complete.
21-22-## 3. Account Termination
23-24-> **Important Notice**
25->
26-> **We reserve the right to terminate, suspend, or restrict access to
27-> your account at any time, for any reason, or for no reason at all, at
28-> our sole discretion.** This includes, but is not limited to,
29-> termination for violation of these Terms, inappropriate conduct, spam,
30-> abuse, or any other behavior we deem harmful to the Service or other
31-> users.
32->
33-> Account termination may result in the loss of access to your
34-> repositories, data, and other content associated with your account. We
35-> are not obligated to provide advance notice of termination, though we
36-> may do so in our discretion.
37-38-## 4. Acceptable Use
39-40-You agree not to use the Service to:
41-42-- Violate any applicable laws or regulations
43-- Infringe upon the rights of others
44-- Upload, store, or share content that is illegal, harmful, threatening,
45- abusive, harassing, defamatory, vulgar, obscene, or otherwise
46- objectionable
47-- Engage in spam, phishing, or other deceptive practices
48-- Attempt to gain unauthorized access to the Service or other users'
49- accounts
50-- Interfere with or disrupt the Service or servers connected to the
51- Service
52-53-## 5. Content and Intellectual Property
54-55-You retain ownership of the content you upload to the Service. By
56-uploading content, you grant us a non-exclusive, worldwide, royalty-free
57-license to use, reproduce, modify, and distribute your content as
58-necessary to provide the Service.
59-60-## 6. Privacy
61-62-Your privacy is important to us. Please review our [Privacy
63-Policy](/privacy), which also governs your use of the Service.
64-65-## 7. Disclaimers
66-67-The Service is provided on an "AS IS" and "AS AVAILABLE" basis. We make
68-no warranties, expressed or implied, and hereby disclaim and negate all
69-other warranties including without limitation, implied warranties or
70-conditions of merchantability, fitness for a particular purpose, or
71-non-infringement of intellectual property or other violation of rights.
72-73-## 8. Limitation of Liability
74-75-In no event shall Tangled, nor its directors, employees, partners,
76-agents, suppliers, or affiliates, be liable for any indirect,
77-incidental, special, consequential, or punitive damages, including
78-without limitation, loss of profits, data, use, goodwill, or other
79-intangible losses, resulting from your use of the Service.
80-81-## 9. Indemnification
82-83-You agree to defend, indemnify, and hold harmless Tangled and its
84-affiliates, officers, directors, employees, and agents from and against
85-any and all claims, damages, obligations, losses, liabilities, costs,
86-or debt, and expenses (including attorney's fees).
87-88-## 10. Governing Law
89-90-These Terms shall be interpreted and governed by the laws of Finland,
91-without regard to its conflict of law provisions.
92-93-## 11. Changes to Terms
94-95-We reserve the right to modify or replace these Terms at any time. If a
96-revision is material, we will try to provide at least 30 days notice
97-prior to any new terms taking effect.
98-99-## 12. Contact Information
100-101-If you have any questions about these Terms of Service, please contact
102-us through our platform or via email.
103-104----
105-106-These terms are effective as of the last updated date shown above and
107-will remain in effect except with respect to any changes in their
108-provisions in the future, which will be in effect immediately after
109-being posted on this page.
···1# tangled
23Hello Tanglers! This is the codebase for
4-[Tangled](https://tangled.sh)—a code collaboration platform built
5on the [AT Protocol](https://atproto.com).
67-Read the introduction to Tangled [here](https://blog.tangled.sh/intro). Join the
8-[Discord](https://chat.tangled.sh) or IRC at [#tangled on
9libera.chat](https://web.libera.chat/#tangled).
1011## docs
···17## security
1819If you've identified a security issue in Tangled, please email
20-[security@tangled.sh](mailto:security@tangled.sh) with details!
···1# tangled
23Hello Tanglers! This is the codebase for
4+[Tangled](https://tangled.org)—a code collaboration platform built
5on the [AT Protocol](https://atproto.com).
67+Read the introduction to Tangled [here](https://blog.tangled.org/intro). Join the
8+[Discord](https://chat.tangled.org) or IRC at [#tangled on
9libera.chat](https://web.libera.chat/#tangled).
1011## docs
···17## security
1819If you've identified a security issue in Tangled, please email
20+[security@tangled.org](mailto:security@tangled.org) with details!