From 17693590a4e52520eee3c637e432582c1395fdbe Mon Sep 17 00:00:00 2001 From: visi Date: Mon, 2 Feb 2026 09:16:19 -0500 Subject: [PATCH 01/25] wip --- synapse/models/base.py | 21 +++- synapse/models/entity.py | 219 +++++++++++++++++++++++++++++---------- synapse/models/orgs.py | 172 +++++++++++++++--------------- 3 files changed, 270 insertions(+), 142 deletions(-) diff --git a/synapse/models/base.py b/synapse/models/base.py index 2942bc27337..46f4caaa7be 100644 --- a/synapse/models/base.py +++ b/synapse/models/base.py @@ -78,7 +78,7 @@ 'doc': 'A hierarchical taxonomy of timeline types.'}), ('meta:event', ('guid', {}), { - 'doc': 'An analytically relevant event in a curated timeline.'}), + 'doc': 'An analytically relevant event.'}), ('meta:event:type:taxonomy', ('taxonomy', {}), { 'interfaces': ( @@ -178,6 +178,13 @@ ), }), + # TODO: discuss interfaces which may only be implemented by a base form + ('meta:attendable', { + 'doc': 'An interface implemented by events which may be attended.'}), + + ('meta:sponsorable', { + 'doc': 'An interface implemented by events which may be sponsored.'}), + ('meta:havable', { 'doc': 'An interface used to describe items that can be possessed by an entity.', 'template': {'title': 'item'}, @@ -467,17 +474,23 @@ ('meta:event', {}, ( + # FIXME discuss instant vs activity ('period', ('ival', {}), { - 'doc': 'The period over which the event occurred.'}), + 'doc': 'The period over which the {title} occurred.'}), - ('title', ('str', {}), { - 'doc': 'A title for the event.'}), + # FIXME redundant with :name / :names and should be removed + # ('title', ('str', {}), { + # 'doc': 'A title for the event.'}), ('desc', ('text', {}), { 'doc': 'A description of the event.'}), + # FIXME conscious decision to fold all "event" types into one taxonomy ('type', ('meta:event:type:taxonomy', {}), { 'doc': 'Type of event.'}), + + #('parent', ('meta:event', {}), { + #'doc': 'The parent event.'}), )), ('meta:event:type:taxonomy', { diff --git a/synapse/models/entity.py b/synapse/models/entity.py index 0e4562a51d1..53a12c8bdf9 100644 --- a/synapse/models/entity.py +++ b/synapse/models/entity.py @@ -8,35 +8,55 @@ ('entity:action', { 'template': {'title': 'action'}, - 'doc': 'Properties which are common to actions taken by entities.', 'props': ( - ('actor', ('entity:actor', {}), { 'doc': 'The actor who carried out the {title}.'}), ('actor:name', ('entity:name', {}), { 'doc': 'The name of the actor who carried out the {title}.'}), - ), - }), - ('entity:attendable', { - 'template': {'title': 'event'}, - 'interfaces': ( - ('geo:locatable', {}), - ('lang:transcript', {}), + #('period', ('ival', {}), { + #'doc': 'The period over which the actor carried out the {title}.'}), + ), + 'doc': 'Properties common to actions taken by entities.'}), + + ('entity:effected', { + 'template': {'effected': 'effected'}, 'props': ( - ('desc', ('text', {}), { - 'doc': 'A description of the {title}.'}), + ('party', ('entity:actor', {}), { + 'doc': 'The entity who was {effected}.'}), - ('period', ('ival', {}), { - 'doc': 'The period of time over which the {title} occurred.'}), + ('party:name', ('entity:name', {}), { + 'doc': 'The name of the entity who was {effected}.'}), - ('parent', ('entity:attendable', {}), { - 'doc': 'The parent event which hosts the {title}.'}), + ('period', ('ival', {}), { + 'doc': 'The period over which the actor carried out the {title}.'}), ), - 'doc': 'Properties common to events which individuals may attend.', - }), + 'doc': 'Properties common to actions taken by entities.'}), + + # ('entity:attendable', { + # 'template': {'title': 'event'}, + # 'interfaces': ( + # ('geo:locatable', {}), + # ('lang:transcript', {}), + # #('entity:activity', {}), + # ), + # 'props': ( + # (#'desc', ('text', {}), { + # # 'doc': 'A description of the {title}.'}), + + # #('actor', ('entity:actor', {}), { + # #'doc': 'The primary organizer of the {title}', + + # #('period', ('ival', {}), { + # #'doc': 'The period of time over which the {title} occurred.'}), + + # ('parent', ('entity:attendable', {}), { + # 'doc': 'The parent event which hosts the {title}.'}), + # ), + # 'doc': 'Properties common to events which individuals may attend.', + # }), ('entity:contactable', { @@ -173,6 +193,9 @@ ('entity:identifier', ('ndef', {'interface': 'entity:identifier'}), { 'doc': 'A node which inherits the entity:identifier interface.'}), + ('entity:action', ('ndef', {'interface': 'entity:action'}), { + 'doc': 'FIXME polyprop place holder'}), + ('entity:name', ('base:name', {}), { 'doc': 'A name used to refer to an entity.'}), @@ -282,11 +305,11 @@ }, 'doc': 'A stated or assessed goal.'}), - ('entity:campaign:type:taxonomy', ('taxonomy', {}), { - 'interfaces': ( - ('meta:taxonomy', {}), - ), - 'doc': 'A hierarchical taxonomy of campaign types.'}), + #('entity:campaign:type:taxonomy', ('taxonomy', {}), { + #'interfaces': ( + #('meta:taxonomy', {}), + #), + #'doc': 'A hierarchical taxonomy of campaign types.'}), ('entity:campaign:status:taxonomy', ('taxonomy', {}), { 'interfaces': ( @@ -294,7 +317,7 @@ ), 'doc': 'A hierarchical taxonomy of campaign statuses.'}), - ('entity:campaign', ('guid', {}), { + ('entity:campaign', ('meta:event', {}), { 'template': {'title': 'campaign'}, 'interfaces': ( ('entity:action', {}), @@ -314,14 +337,62 @@ ('entity:conflict', ('guid', {}), { 'doc': 'Represents a conflict where two or more campaigns have mutually exclusive goals.'}), - ('entity:contribution', ('guid', {}), { - 'template': {'title': 'contribution'}, + #('entity:contribution:type:taxonomy', ('taxonomy', {}), { + #'doc': 'A hierarchical taxonomy of contribution types.'}), + + ('entity:effected', ('guid', {}), { + + ('event', ('meta:event', {}), { + 'doc': 'The event which effected the entity.'}), + + ('party', ('entity:actor', {}), { + 'doc': 'The party which was effected by the event.'}), + }), + ('risk:impacted', ('entity:effected', {}), {}), + #('meta:impact' -> risk:impact -> risk:damage + + ('entity:observed', ('entity:effected', {}), {}), + + ('entity:activity', ('guid', {}), { 'interfaces': ( ('entity:action', {}), ), - 'doc': 'Represents a specific instance of contributing material support to a campaign.'}), + 'props': ( + ('actor:roles', ('array', {'type': 'base:name'}), { + 'doc': 'The roles of the actor in the activity.'}), + ), + 'doc': 'Activity carried out by an actor.'}), + + ('entity:support', ('entity:activity', {}), { + 'template': { + 'title': 'support', + 'supported': 'supported', + }, + 'doc': 'Represents an actor having supported an action.', + }), + + ('entity:contribution', ('entity:activity', {}), { + 'template': { + 'title': 'contribution', + 'supported': 'contributed to', + }, + 'interfaces': ( + ('entity:action', {}), + ), + }), + + ('entity:participation', ('entity:activity', {}), { + 'template': { + 'title': 'participation', + 'suppoted': 'particpated in', + }, + }), ('entity:discovery', ('guid', {}), { + 'templates': {'title': 'discovery'}, + 'interfaces': ( + ('entity:action', {}), + ), 'doc': 'A discovery made by an actor.'}), ), @@ -423,18 +494,18 @@ ('entity:attendee', {}, ( - ('person', ('entity:individual', {}), { - 'doc': 'The person who attended the event.'}), + # ('person', ('entity:individual', {}), { + # 'doc': 'The person who attended the event.'}), - ('period', ('ival', {}), { - 'doc': 'The time period when the person attended the event.'}), + # ('period', ('ival', {}), { + # 'doc': 'The time period when the person attended the event.'}), - ('roles', ('array', {'type': 'base:name', 'split': ','}), { - 'doc': 'List of the roles the person had at the event.'}), + #('roles', ('array', {'type': 'base:name', 'split': ','}), { + #'doc': 'List of the roles the person had at the event.'}), - ('event', ('entity:attendable', {}), { - 'prevnames': ('meet', 'conference', 'conference:event', 'contest', 'preso'), - 'doc': 'The event that the person attended.'}), + # ('event', ('entity:attendable', {}), { + # 'prevnames': ('meet', 'conference', 'conference:event', 'contest', 'preso'), + # 'doc': 'The event that the person attended.'}), # ('link', ('entity:link', {}), { # 'doc': 'The remote communication mechanism used by the person to attend the event.'}), @@ -466,8 +537,8 @@ ('slogan', ('lang:phrase', {}), { 'doc': 'The slogan used by the campaign.'}), - ('actors', ('array', {'type': 'entity:actor', 'split': ','}), { - 'doc': 'Actors who participated in the campaign.'}), + #('actors', ('array', {'type': 'entity:actor', 'split': ','}), { + #'doc': 'Actors who participated in the campaign.'}), ('success', ('bool', {}), { 'doc': 'Set to true if the campaign achieved its goals.'}), @@ -476,13 +547,14 @@ ('sophistication', ('meta:score', {}), { 'doc': 'The assessed sophistication of the campaign.'}), - ('type', ('entity:campaign:type:taxonomy', {}), { - 'doc': 'A type taxonomy entry for the campaign.', - 'prevnames': ('camptype',)}), + #('type', ('entity:campaign:type:taxonomy', {}), { + #'doc': 'A type taxonomy entry for the campaign.', + #'prevnames': ('camptype',)}), - ('period', ('ival', {}), { - 'doc': 'The time interval when the entity was running the campaign.'}), + #('period', ('ival', {}), { + #'doc': 'The time interval when the entity was running the campaign.'}), + # TODO: cost:budget cost:actual ? ('cost', ('econ:price', {}), { 'protocols': { 'econ:adjustable': {'props': {'time': 'period.min', 'currency': 'currency'}}, @@ -498,12 +570,12 @@ ('currency', ('econ:currency', {}), { 'doc': 'The currency used to record econ:price properties.'}), - ('team', ('ou:team', {}), { - 'doc': 'The org team responsible for carrying out the campaign.'}), + #('team', ('ou:team', {}), { + #'doc': 'The org team responsible for carrying out the campaign.'}), # FIXME overfit? - ('conflict', ('entity:conflict', {}), { - 'doc': 'The conflict in which this campaign is a primary participant.'}), + #('conflict', ('entity:conflict', {}), { + #'doc': 'The conflict in which this campaign is a primary participant.'}), ('tag', ('syn:tag', {}), { 'doc': 'The tag used to annotate nodes that are associated with the campaign.'}), @@ -517,24 +589,61 @@ ('period', ('ival', {}), { 'doc': 'The period of time when the conflict was ongoing.'}), - ('adversaries', ('array', {'type': 'entity:actor'}), { - 'doc': 'The primary adversaries in conflict with one another.'}), + #('adversaries', ('array', {'type': 'entity:actor'}), { + #'doc': 'The primary adversaries in conflict with one another.'}), )), - ('entity:contribution', {}, ( - ('campaign', ('entity:campaign', {}), { - 'doc': 'The campaign receiving the contribution.'}), + # other terse entity nouns: subject, party, target + # entity:effected + # :event= + # :party= + # :party= - # FIXME - :price / :price:currency ( and the interface ) + + # entity:activity + # :role=attacker + + # entity:attended + # :period + # :actor= + # :event= + + # entity:registered + # :time + # :actor= + # :event= + + # entity:contributed + # entity:participated + # :actor= + # :event= + + ('entity:support', {}, ( + ('event', ('entity:action', {}), { + 'doc': 'The action which the actor {supported}.'}), + )), + + ('entity:contribution', {}, ( + + # recipient? mix of entity and action? ('value', ('econ:price', {}), { 'doc': 'The assessed value of the contribution.'}), ('currency', ('econ:currency', {}), { 'doc': 'The currency used for the assessed value.'}), - - ('time', ('time', {}), { - 'doc': 'The time the contribution occurred.'}), )), + ('entity:sponsorship', {}, ( + ('event', ('meta:sponsorable', {}), { + 'doc': 'The event which was sponsored by the actor.'}), + )), + ('entity:attendance' + ('entity:participation', {}, ()), + # -(has)> econ:payment + # -(has)> entity:ownerhip ( representing the transfer of ownership of a thing ) + ('entity:discovery', {}, ( diff --git a/synapse/models/orgs.py b/synapse/models/orgs.py index 5990cc47513..9b0b92d2973 100644 --- a/synapse/models/orgs.py +++ b/synapse/models/orgs.py @@ -13,49 +13,50 @@ 'interfaces': ( - ('ou:attendable', { - 'template': {'title': 'event'}, - 'interfaces': ( - ('meta:havable', {}), - ('entity:attendable', {}), - ), - 'props': ( - - ('name', ('meta:name', {}), { - 'alts': ('names',), - 'ex': 'cyberwarcon 2025', - 'doc': 'The name of the {title}.'}), - - ('name:base', ('meta:name', {}), { - 'ex': 'cyberwarcon', - 'doc': 'The base name of the {title} (for a recurring event).'}), - - ('names', ('array', {'type': 'meta:name'}), { - 'doc': 'An array of alternate names for the {title}.'}), - ), - 'doc': 'An interface which is inherited by all organized events.'}), - - ('ou:sponsored', { - 'template': {'title': 'event'}, - 'interfaces': ( - ('ou:attendable', {}), - ), - 'props': ( - - ('website', ('inet:url', {}), { - 'prevnames': ('url',), - 'doc': 'The URL of the {title} website.'}), - - ('contact', ('entity:contact', {}), { - 'doc': 'Contact information for the {title}.'}), - - ('sponsors', ('array', {'type': 'entity:actor'}), { - 'doc': 'The entities which sponsored the {title}.'}), - - ('organizers', ('array', {'type': 'entity:actor'}), { - 'doc': 'An array of {title} organizers.'}), - ), - 'doc': 'Properties which are common to events which are hosted or sponsored by organizations.'}), + # ('ou:attendable', { + # 'template': {'title': 'event'}, + # 'interfaces': ( + # #('meta:havable', {}), + # ('entity:attendable', {}), + # ), + # 'props': ( + + # ('name', ('meta:name', {}), { + # 'alts': ('names',), + # 'ex': 'cyberwarcon 2025', + # 'doc': 'The name of the {title}.'}), + + # ('name:base', ('meta:name', {}), { + # 'ex': 'cyberwarcon', + # 'doc': 'The base name of the {title} (for a recurring event).'}), + + # ('names', ('array', {'type': 'meta:name'}), { + # 'doc': 'An array of alternate names for the {title}.'}), + # ), + # 'doc': 'An interface which is inherited by all organized events.'}), + + # FIXME: all this should become part of entity:activity + # ('ou:sponsored', { + # 'template': {'title': 'event'}, + # 'interfaces': ( + # ('ou:attendable', {}), + # ), + # 'props': ( + + # ('website', ('inet:url', {}), { + # 'prevnames': ('url',), + # 'doc': 'The URL of the {title} website.'}), + + # ('contact', ('entity:contact', {}), { + # 'doc': 'Contact information for the {title}.'}), + + # #('sponsors', ('array', {'type': 'entity:actor'}), { + # #'doc': 'The entities which sponsored the {title}.'}), + + # #('organizers', ('array', {'type': 'entity:actor'}), { + # #'doc': 'An array of {title} organizers.'}), + # ), + # 'doc': 'Properties which are common to events which are hosted or sponsored by organizations.'}), ), 'types': ( ('ou:sic', ('str', {'regex': r'^[0-9]{4}$'}), { @@ -193,34 +194,34 @@ }, 'doc': 'A conference.'}), - ('ou:event:type:taxonomy', ('taxonomy', {}), { - 'interfaces': ( - ('meta:taxonomy', {}), - ), - 'doc': 'A hierarchical taxonomy of event types.'}), - - ('ou:event', ('guid', {}), { - 'template': {'title': 'event'}, - 'prevnames': ('ou:conference:event',), - 'interfaces': ( - ('ou:sponsored', {}), - ), - 'display': { - 'columns': ( - {'type': 'prop', 'opts': {'name': 'name'}}, - {'type': 'prop', 'opts': {'name': 'parent::name'}}, - # TODO allow columns to use virtual props - # {'type': 'prop', 'opts': {'name': 'period.min'}}, - # {'type': 'prop', 'opts': {'name': 'period.max'}}, - ), - }, - 'doc': 'An generic organized event.'}), - - ('ou:contest:type:taxonomy', ('taxonomy', {}), { - 'interfaces': ( - ('meta:taxonomy', {}), - ), - 'doc': 'A hierarchical taxonomy of contest types.'}), + #('ou:event:type:taxonomy', ('taxonomy', {}), { + #'interfaces': ( + #('meta:taxonomy', {}), + #), + #'doc': 'A hierarchical taxonomy of event types.'}), + + # ('ou:event', ('guid', {}), { + # 'template': {'title': 'event'}, + # 'prevnames': ('ou:conference:event',), + # 'interfaces': ( + # ('ou:sponsored', {}), + # ), + # 'display': { + # 'columns': ( + # {'type': 'prop', 'opts': {'name': 'name'}}, + # {'type': 'prop', 'opts': {'name': 'parent::name'}}, + # # TODO allow columns to use virtual props + # # {'type': 'prop', 'opts': {'name': 'period.min'}}, + # # {'type': 'prop', 'opts': {'name': 'period.max'}}, + # ), + # }, + # 'doc': 'An generic organized event.'}), + + # ('ou:contest:type:taxonomy', ('taxonomy', {}), { + # 'interfaces': ( + # ('meta:taxonomy', {}), + # ), + # 'doc': 'A hierarchical taxonomy of contest types.'}), ('ou:contest', ('guid', {}), { 'template': {'title': 'contest'}, @@ -313,6 +314,7 @@ ), }}), + # FIXME ou:employment -> meta:event? ('ou:employment:type:taxonomy', ('taxonomy', {}), { 'ex': 'fulltime.salary', 'interfaces': ( @@ -346,8 +348,8 @@ ('ou:job:type:taxonomy', { 'prevnames': ('ou:jobtype',)}, ()), - ('ou:employment:type:taxonomy', { - 'prevnames': ('ou:employment',)}, ()), + #('ou:employment:type:taxonomy', { + #'prevnames': ('ou:employment',)}, ()), ('ou:opening', {}, ( @@ -443,6 +445,7 @@ )), + # FIXME entity:supported :event=? ('ou:candidate:referral', {}, ( ('candidate', ('ou:candidate', {}), { @@ -730,20 +733,23 @@ 'doc': 'A file containing a recording of the presentation.'}), )), ('ou:meeting', {}, ( - ('hosts', ('array', {'type': 'entity:actor'}), { - 'doc': 'The contacts who hosted or called the meeting.'}), + #('hosts', ('array', {'type': 'entity:actor'}), { + #'doc': 'The contacts who hosted or called the meeting.'}), )), - ('ou:conference', {}, ()), - ('ou:event', {}, ( - ('type', ('ou:event:type:taxonomy', {}), { - 'doc': 'The type of event.'}), + ('ou:conference', {}, ( + ('family:name', ('base:name', {}), { + 'doc': 'The name of the family of conferences.'}), )), - ('ou:contest:type:taxonomy', {}, ()), + #('ou:event', {}, ( + #('type', ('ou:event:type:taxonomy', {}), { + #'doc': 'The type of event.'}), + #)), + #('ou:contest:type:taxonomy', {}, ()), ('ou:contest', {}, ( - ('type', ('ou:contest:type:taxonomy', {}), { - 'ex': 'cyber.ctf', - 'doc': 'The type of contest.'}), + #('type', ('ou:contest:type:taxonomy', {}), { + #'ex': 'cyber.ctf', + #'doc': 'The type of contest.'}), )), ('ou:contest:result', {}, ( From b2a6a7c9b03ae49cccb6be22c42aed363d722c19 Mon Sep 17 00:00:00 2001 From: visi Date: Tue, 3 Feb 2026 13:20:12 -0500 Subject: [PATCH 02/25] wip --- synapse/datamodel.py | 3 + synapse/models/base.py | 81 ++++++++--- synapse/models/belief.py | 19 +-- synapse/models/doc.py | 19 ++- synapse/models/entity.py | 283 +++++++++++++++++------------------- synapse/models/geopol.py | 14 +- synapse/models/orgs.py | 25 +++- synapse/models/person.py | 44 +++--- synapse/models/risk.py | 117 +++++++++------ synapse/models/transport.py | 7 +- 10 files changed, 342 insertions(+), 270 deletions(-) diff --git a/synapse/datamodel.py b/synapse/datamodel.py index 570ed36159b..fccd66a5dbf 100644 --- a/synapse/datamodel.py +++ b/synapse/datamodel.py @@ -1368,6 +1368,9 @@ def addIface(self, name, info): self.ifaces[name] = info + # FIXME polyprops + self.addType(name, 'ndef', {'interface': name}, {'doc': 'FIXME POLYPROP PLACE HOLDER'}) + def reqTypeNotInUse(self, typename): if self.propsbytype.get(typename): mesg = f'Cannot delete type {typename} as it is still in use by properties.' diff --git a/synapse/models/base.py b/synapse/models/base.py index 46f4caaa7be..176bb2e4e16 100644 --- a/synapse/models/base.py +++ b/synapse/models/base.py @@ -78,8 +78,31 @@ 'doc': 'A hierarchical taxonomy of timeline types.'}), ('meta:event', ('guid', {}), { + 'template': {'title': 'event'}, + 'interfaces': ( + ('meta:causal', {}), + ), + 'props': ( + + ('time', ('time', {}), { + 'doc': 'The time that the {title} occured.'}), + + ('type', ('meta:event:type:taxonomy', {}), { + 'doc': 'The type of event.'}), + ), 'doc': 'An analytically relevant event.'}), + ('meta:activity', ('guid', {}), { + 'template': {'title': 'activity'}, + 'interfaces': ( + ('meta:causal', {}), + ), + 'props': ( + ('period', ('time', {}), { + 'doc': 'The period over which the {activity} occured.'}), + ), + 'doc': 'Analytically relevant activity.'}), + ('meta:event:type:taxonomy', ('taxonomy', {}), { 'interfaces': ( ('meta:taxonomy', {}), @@ -179,17 +202,28 @@ }), # TODO: discuss interfaces which may only be implemented by a base form + ('meta:promoted', { + 'props': ( + ('website', ('inet:url', {}), { + 'doc': 'The URL of the {title} website.'}), + + ('social:accounts', ('array', {'type': 'inet:service:account'}), { + 'doc': 'Social media accounts for the {title}.'}), + ), + 'doc': 'Properties common to promoted events or activities.'}), + ('meta:attendable', { - 'doc': 'An interface implemented by events which may be attended.'}), + 'doc': 'An interface implemented by activities which may be attended.'}), ('meta:sponsorable', { - 'doc': 'An interface implemented by events which may be sponsored.'}), + 'doc': 'An interface implemented by activities which may be sponsored.'}), ('meta:havable', { 'doc': 'An interface used to describe items that can be possessed by an entity.', 'template': {'title': 'item'}, 'props': ( + # TODO - alliance / coalition / etc makes this workable... ('owner', ('entity:actor', {}), { 'doc': 'The current owner of the {title}.'}), @@ -292,6 +326,16 @@ ), }), + ('meta:causal', { + 'props': ( + ('name', ('base:name', {}), { + 'doc': 'The name of the {title}.'}), + + ('desc', ('text', {}), { + 'doc': 'A description of the {title}.'}), + ), + 'doc': 'Properties common to events and activity.'}), + ('meta:usable', { 'template': {'title': 'item'}, 'props': ( @@ -365,6 +409,9 @@ (('meta:technique', 'addresses', 'risk:vuln'), { 'doc': 'The technique addresses the vulnerability.'}), + + (('meta:causal', 'leadto', 'meta:causal'), { + 'doc': 'The source event lead to the target event.'}), ), 'forms': ( @@ -472,26 +519,26 @@ ('meta:timeline:type:taxonomy', { 'prevnames': ('meta:timeline:taxonomy',)}, ()), - ('meta:event', {}, ( + # ('meta:event', {}, ( - # FIXME discuss instant vs activity - ('period', ('ival', {}), { - 'doc': 'The period over which the {title} occurred.'}), + # # FIXME discuss instant vs activity + # #('period', ('ival', {}), { + # #'doc': 'The period over which the {title} occurred.'}), - # FIXME redundant with :name / :names and should be removed - # ('title', ('str', {}), { - # 'doc': 'A title for the event.'}), + # # FIXME redundant with :name / :names and should be removed + # # ('title', ('str', {}), { + # # 'doc': 'A title for the event.'}), - ('desc', ('text', {}), { - 'doc': 'A description of the event.'}), + # ('desc', ('text', {}), { + # 'doc': 'A description of the event.'}), - # FIXME conscious decision to fold all "event" types into one taxonomy - ('type', ('meta:event:type:taxonomy', {}), { - 'doc': 'Type of event.'}), + # # FIXME conscious decision to fold all "event" types into one taxonomy + # ('type', ('meta:event:type:taxonomy', {}), { + # 'doc': 'Type of event.'}), - #('parent', ('meta:event', {}), { - #'doc': 'The parent event.'}), - )), + # #('parent', ('meta:event', {}), { + # #'doc': 'The parent event.'}), + # )), ('meta:event:type:taxonomy', { 'prevnames': ('meta:event:taxonomy',)}, ()), diff --git a/synapse/models/belief.py b/synapse/models/belief.py index 0fa17248a46..a4160760338 100644 --- a/synapse/models/belief.py +++ b/synapse/models/belief.py @@ -14,7 +14,12 @@ ('belief:tenet', ('guid', {}), { 'doc': 'A concrete tenet potentially shared by multiple belief systems.'}), - ('belief:subscriber', ('guid', {}), { + ('belief:subscriber', ('entity:activity', {}), { + 'template': {'title': 'subscribed'}, + 'props': ( + ('system', ('belief:system', {}), { + 'doc': 'The belief system to which the contact subscribes.'}), + ), 'doc': 'A contact which subscribes to a belief system.'}), ), 'forms': ( @@ -46,18 +51,6 @@ 'doc': 'A description of the tenet.'}), )), - ('belief:subscriber', {}, ( - - ('contact', ('entity:individual', {}), { - 'doc': 'The individual who subscribes to the belief system.'}), - - ('system', ('belief:system', {}), { - 'doc': 'The belief system to which the contact subscribes.'}), - - ('period', ('ival', {}), { - 'prevnames': ('began', 'ended'), - 'doc': 'The time period when the contact subscribed to the belief system.'}), - )), ), 'edges': ( diff --git a/synapse/models/doc.py b/synapse/models/doc.py index 812c18e035c..03cc8af077d 100644 --- a/synapse/models/doc.py +++ b/synapse/models/doc.py @@ -68,6 +68,10 @@ 'doc': 'The name of the file containing the {title} contents.'}), ), }), + + ('doc:signable', { + 'doc': 'An interface applied to documents which are signed by individuals.'}), + ), 'types': ( @@ -139,10 +143,9 @@ ('doc:contract', ('guid', {}), { 'prevnames': ('ou:contract',), + 'template': {'title': 'contract'}, 'interfaces': ( - ('doc:document', {'template': { - 'title': 'contract', - 'type': 'doc:contract:type:taxonomy'}}), + ('doc:document', {}), ), 'doc': 'A contract between multiple entities.'}), @@ -159,6 +162,13 @@ ('doc:reference', ('guid', {}), { 'doc': 'A reference included in a source.'}), + ('doc:signed', ('entity:event', {}), { + 'props': ( + ('document', ('doc:signable', {}), { + 'doc': 'The document which was signed by the actor.'}), + ), + 'doc': 'An event where an actor signed a document.'}), + ), 'edges': ( (('doc:contract', 'has', 'doc:requirement'), { @@ -244,9 +254,6 @@ ('parties', ('array', {'type': 'entity:actor'}), { 'doc': 'The entities bound by the contract.'}), - ('signers', ('array', {'type': 'entity:individual'}), { - 'doc': 'The individuals who signed the contract.'}), - ('period', ('ival', {}), { 'doc': 'The time period when the contract is in effect.'}), diff --git a/synapse/models/entity.py b/synapse/models/entity.py index 53a12c8bdf9..3ca0a3b6c71 100644 --- a/synapse/models/entity.py +++ b/synapse/models/entity.py @@ -15,48 +15,28 @@ ('actor:name', ('entity:name', {}), { 'doc': 'The name of the actor who carried out the {title}.'}), - #('period', ('ival', {}), { - #'doc': 'The period over which the actor carried out the {title}.'}), - - ), - 'doc': 'Properties common to actions taken by entities.'}), - - ('entity:effected', { - 'template': {'effected': 'effected'}, - 'props': ( - ('party', ('entity:actor', {}), { - 'doc': 'The entity who was {effected}.'}), - - ('party:name', ('entity:name', {}), { - 'doc': 'The name of the entity who was {effected}.'}), + ('actor:roles', ('array', {'type': 'base:name'}), { + 'doc': 'The roles of the actor in the {title}.'}), - ('period', ('ival', {}), { - 'doc': 'The period over which the actor carried out the {title}.'}), ), 'doc': 'Properties common to actions taken by entities.'}), - # ('entity:attendable', { - # 'template': {'title': 'event'}, - # 'interfaces': ( - # ('geo:locatable', {}), - # ('lang:transcript', {}), - # #('entity:activity', {}), - # ), + # ('entity:affected', { + # 'template': {'affected': 'affected'}, # 'props': ( - # (#'desc', ('text', {}), { - # # 'doc': 'A description of the {title}.'}), + # ('event', ('meta:causal', {}), { + # 'doc': 'The event which affected the entity.'}), - # #('actor', ('entity:actor', {}), { - # #'doc': 'The primary organizer of the {title}', + # ('party', ('entity:actor', {}), { + # 'doc': 'The entity who was {affected}.'}), - # #('period', ('ival', {}), { - # #'doc': 'The period of time over which the {title} occurred.'}), + # ('party:name', ('entity:name', {}), { + # 'doc': 'The name of the entity who was {affected}.'}), - # ('parent', ('entity:attendable', {}), { - # 'doc': 'The parent event which hosts the {title}.'}), + # ('period', ('ival', {}), { + # 'doc': 'The period over which the entity was {affected}.'}), # ), - # 'doc': 'Properties common to events which individuals may attend.', - # }), + # 'doc': 'Properties common to entities being affected by an event.'}), ('entity:contactable', { @@ -193,8 +173,8 @@ ('entity:identifier', ('ndef', {'interface': 'entity:identifier'}), { 'doc': 'A node which inherits the entity:identifier interface.'}), - ('entity:action', ('ndef', {'interface': 'entity:action'}), { - 'doc': 'FIXME polyprop place holder'}), + #('entity:action', ('ndef', {'interface': 'entity:action'}), { + #'doc': 'FIXME polyprop place holder'}), ('entity:name', ('base:name', {}), { 'doc': 'A name used to refer to an entity.'}), @@ -272,9 +252,6 @@ ('entity:had', ('guid', {}), { 'doc': 'An item which was possessed by an actor.'}), - ('entity:attendee', ('guid', {}), { - 'doc': 'A person attending an event.'}), - ('entity:conversation', ('guid', {}), { 'doc': 'A conversation between entities.'}), @@ -305,22 +282,21 @@ }, 'doc': 'A stated or assessed goal.'}), - #('entity:campaign:type:taxonomy', ('taxonomy', {}), { - #'interfaces': ( - #('meta:taxonomy', {}), - #), - #'doc': 'A hierarchical taxonomy of campaign types.'}), + # ('entity:campaign:type:taxonomy', ('taxonomy', {}), { + # 'interfaces': ( + # ('meta:taxonomy', {}), + # ), + # 'doc': 'A hierarchical taxonomy of campaign types.'}), - ('entity:campaign:status:taxonomy', ('taxonomy', {}), { - 'interfaces': ( - ('meta:taxonomy', {}), - ), - 'doc': 'A hierarchical taxonomy of campaign statuses.'}), + # ('entity:campaign:status:taxonomy', ('taxonomy', {}), { + # 'interfaces': ( + # ('meta:taxonomy', {}), + # ), + # 'doc': 'A hierarchical taxonomy of campaign statuses.'}), - ('entity:campaign', ('meta:event', {}), { + ('entity:campaign', ('meta:activity', {}), { 'template': {'title': 'campaign'}, 'interfaces': ( - ('entity:action', {}), ('meta:reported', {}), ), 'display': { @@ -334,64 +310,79 @@ }, 'doc': 'Activity in pursuit of a goal.'}), - ('entity:conflict', ('guid', {}), { - 'doc': 'Represents a conflict where two or more campaigns have mutually exclusive goals.'}), + ('entity:conflict', ('meta:activity', {}), { + 'props': ( + ('adversaries', ('array', {'type': 'entity:actor'}), { + 'doc': 'The primary adversaries in conflict with one another.'}), + ), + 'doc': 'Represents a conflict where two or more actors have mutually exclusive goals.'}), - #('entity:contribution:type:taxonomy', ('taxonomy', {}), { - #'doc': 'A hierarchical taxonomy of contribution types.'}), + # TODO - belief:subscriber= + ('entity:event', ('meta:event', {}), { + 'interfaces': ( + ('entity:action', {}), + ), + 'doc': 'An event carried out by an actor.'}), - ('entity:effected', ('guid', {}), { + ('entity:activity', ('meta:activity', {}), { + 'interfaces': ( + ('entity:action', {}), + ), + 'doc': 'Activity carried out by an actor.'}), - ('event', ('meta:event', {}), { - 'doc': 'The event which effected the entity.'}), - ('party', ('entity:actor', {}), { - 'doc': 'The party which was effected by the event.'}), - }), - ('risk:impacted', ('entity:effected', {}), {}), - #('meta:impact' -> risk:impact -> risk:damage + ('entity:affected', ('meta:activity', {}), { + 'props': ( + ('party', ('entity:actor', {}), { + 'doc': 'The party which was affected.'}), - ('entity:observed', ('entity:effected', {}), {}), + ('party:name', ('entity:name', {}), { + 'doc': 'The name of the party which was affected.'}), + ), + 'doc': 'An entity which was affected by events.'}), - ('entity:activity', ('guid', {}), { - 'interfaces': ( - ('entity:action', {}), + # entity:knew / entity:awareof? + ('entity:observed', ('entity:affected', {}), { + 'props': ( + ('event', ('meta:causal', {}), { + 'doc': 'The event which was observed by the entity.'}), ), + 'doc': 'Passive observation of an event by an entity.'}), + + ('entity:involved', ('entity:activity', {}), { 'props': ( - ('actor:roles', ('array', {'type': 'base:name'}), { - 'doc': 'The roles of the actor in the activity.'}), + ('event', ('meta:causal', {}), { + 'doc': 'The event or activity the actor was involved in.'}), ), - 'doc': 'Activity carried out by an actor.'}), + 'doc': "Represents an actor's active involvement with an event."}) - ('entity:support', ('entity:activity', {}), { - 'template': { - 'title': 'support', - 'supported': 'supported', - }, - 'doc': 'Represents an actor having supported an action.', - }), + ('entity:support', ('entity:involved', {}), { + 'template': {'title': 'support'}, + 'doc': 'Represents an actor having materially supported an event.'}), - ('entity:contribution', ('entity:activity', {}), { - 'template': { - 'title': 'contribution', - 'supported': 'contributed to', - }, - 'interfaces': ( - ('entity:action', {}), + #('entity:contribution:type:taxonomy', ('taxonomy', {}), { + #'doc': 'A hierarchical taxonomy of contribution types.'}), + + ('entity:contribution', ('entity:support', {}), { + 'template': {'title': 'contribution'}, + 'props': ( + ('value', ('econ:price', {}), { + 'doc': 'The total value of the actors contribution.'}), ), - }), + 'doc': 'An actor providing support for an event or activity.'}), - ('entity:participation', ('entity:activity', {}), { - 'template': { - 'title': 'participation', - 'suppoted': 'particpated in', - }, - }), + ('entity:participation', ('entity:involved', {}), { + 'template': {'title': 'participation'}, + 'props': ( + # TODO - :level=? + ), + 'doc': 'An actor actively participating in an event or activity.'}), - ('entity:discovery', ('guid', {}), { + ('entity:discovered', ('entity:event', {}), { 'templates': {'title': 'discovery'}, - 'interfaces': ( - ('entity:action', {}), + 'props': ( + ('item', ('meta:discoverable', {}), { + 'doc': 'The item which was discovered.'}), ), 'doc': 'A discovery made by an actor.'}), @@ -492,26 +483,6 @@ 'doc': 'The target entity in the relationship.'}), )), - ('entity:attendee', {}, ( - - # ('person', ('entity:individual', {}), { - # 'doc': 'The person who attended the event.'}), - - # ('period', ('ival', {}), { - # 'doc': 'The time period when the person attended the event.'}), - - #('roles', ('array', {'type': 'base:name', 'split': ','}), { - #'doc': 'List of the roles the person had at the event.'}), - - # ('event', ('entity:attendable', {}), { - # 'prevnames': ('meet', 'conference', 'conference:event', 'contest', 'preso'), - # 'doc': 'The event that the person attended.'}), - - # ('link', ('entity:link', {}), { - # 'doc': 'The remote communication mechanism used by the person to attend the event.'}), - )), - - ('entity:goal:type:taxonomy', {}, ()), ('entity:goal', {}, ( @@ -581,20 +552,20 @@ 'doc': 'The tag used to annotate nodes that are associated with the campaign.'}), )), - ('entity:conflict', {}, ( + # ('entity:conflict', {}, ( - ('name', ('meta:name', {}), { - 'doc': 'The name of the conflict.'}), + # ('name', ('meta:name', {}), { + # 'doc': 'The name of the conflict.'}), - ('period', ('ival', {}), { - 'doc': 'The period of time when the conflict was ongoing.'}), + # ('period', ('ival', {}), { + # 'doc': 'The period of time when the conflict was ongoing.'}), - #('adversaries', ('array', {'type': 'entity:actor'}), { - #'doc': 'The primary adversaries in conflict with one another.'}), - )), + # ('adversaries', ('array', {'type': 'entity:actor'}), { + # 'doc': 'The primary adversaries in conflict with one another.'}), + # )), # other terse entity nouns: subject, party, target - # entity:effected + # entity:affected # :event= # :party= # :event= - ('entity:support', {}, ( - ('event', ('entity:action', {}), { - 'doc': 'The action which the actor {supported}.'}), - )), + # ('entity:support', {}, ( + # ('event', ('entity:action', {}), { + # 'doc': 'The action which the actor {supported}.'}), + # )), - ('entity:contribution', {}, ( + ('entity:contribution', ('entity:activity', {}), { + 'props': ( - # recipient? mix of entity and action? - ('value', ('econ:price', {}), { - 'doc': 'The assessed value of the contribution.'}), + ('event', ('meta:causal', {}), { + 'doc': 'The activity supported by the actor.'}), - ('currency', ('econ:currency', {}), { - 'doc': 'The currency used for the assessed value.'}), - )), - ('entity:sponsorship', {}, ( - ('event', ('meta:sponsorable', {}), { - 'doc': 'The event which was sponsored by the actor.'}), - )), - ('entity:attendance' - ('entity:participation', {}, ()), - # -(has)> econ:payment - # -(has)> entity:ownerhip ( representing the transfer of ownership of a thing ) + ('value', ('econ:price', {}), { + 'doc': 'The assessed value of the contribution.'}), + ('currency', ('econ:currency', {}), { + 'doc': 'The currency used for the assessed value.'}), + ), + 'doc': 'An instance of an entity contributing to an event.'}), - ('entity:discovery', {}, ( + # ('entity:participated', ('meta:activity', {}), { + # 'props': ( + # ('event', ('meta:causal', {}), { + # 'doc': 'The event that the actor participated in.'}), + # ), + # 'doc': 'An instance of an entity actively participating in an event.'}), - ('actor', ('entity:actor', {}), { - 'doc': 'The actor who made the discovery.'}), + ('entity:sponsored', ('entity:activity', {}), { + 'props': ( + ('event', ('meta:sponsorable', {}), { + 'doc': 'The event which was sponsored by the actor.'}), - ('time', ('time', {}), { - 'doc': 'The time when the discovery was made.'}), + ('value', ('econ:price', {}), { + 'doc': 'The assessed value of the contribution.'}), + ), + 'doc': 'An instance of an actor sponsoring an event.'}), - ('item', ('meta:discoverable', {}), { - 'doc': 'The item which was discovered.'}), - )), + ('entity:attended', ('entity:activity', {}), { + 'props': ( + ('event', ('meta:attendable', {}), { + 'doc': 'The event which the actor attended.'}), + ), + 'doc': 'An intance of an entity attending an organized event.'}), + + ('entity:registered', ('entity:event', {}), { + 'props': ( + ('event', ('meta:attendable', {}), { + 'doc': 'The event which the actor registered attended.'}), + ), + 'doc': 'An instance of an entity registering for an organized event.'}), ), }), diff --git a/synapse/models/geopol.py b/synapse/models/geopol.py index e661937c52b..ae7dd8f6676 100644 --- a/synapse/models/geopol.py +++ b/synapse/models/geopol.py @@ -36,7 +36,9 @@ ('pol:term', ('guid', {}), { 'doc': 'A term in office held by a specific individual.'}), - ('pol:candidate', ('guid', {}), { + ('pol:candidacy', ('entity:activity', {}), { + 'template': {'title': 'candidacy'}, + 'prevnames': ('pol:candidate',), 'doc': 'A candidate for office in a specific race.'}), ('pol:pollingplace', ('guid', {}), { @@ -187,13 +189,17 @@ ('party', ('ou:org', {}), { 'doc': 'The political party of the person who held office during the term.'}), )), - ('pol:candidate', {}, ( + # TODO pol:candidacy= + ('pol:candidacy', {}, ( ('id', ('meta:id', {}), { 'doc': 'A unique ID for the candidate issued by an election authority.'}), - ('contact', ('entity:contact', {}), { - 'doc': 'The contact information of the candidate.'}), + # ('contact', ('entity:contact', {}), { + # 'doc': 'The contact information of the candidate.'}), + + ('announced', ('time', {}), { + 'doc': 'The time when the candidacy was publicly announced.'}), ('race', ('pol:race', {}), { 'doc': 'The race the candidate is participating in.'}), diff --git a/synapse/models/orgs.py b/synapse/models/orgs.py index 9b0b92d2973..71dfe3c3d48 100644 --- a/synapse/models/orgs.py +++ b/synapse/models/orgs.py @@ -158,16 +158,21 @@ ('ou:position', ('guid', {}), { 'doc': 'A position within an org which can be organized into an org chart with replaceable contacts.'}), - ('ou:meeting', ('guid', {}), { + ('ou:meeting', ('meta:activity', {}), { 'prevnames': ('ou:meet',), + 'template': {'title': 'meeting'}, 'interfaces': ( - ('ou:attendable', {'template': {'title': 'meeting'}}), + ('meta:attendable', {}), ), 'doc': 'A meeting.'}), - ('ou:preso', ('guid', {}), { + ('ou:presentation', ('meta:activity', {}), { + 'prevnames': ('ou:preso',), + 'template': {'title': 'presentation'}, 'interfaces': ( - ('ou:sponsored', {'template': {'title': 'presentation'}}), + ('meta:promoted', {}), + ('meta:attendable', {}), + ('meta:sponsorable', {}), ), 'display': { 'columns': ( @@ -178,10 +183,12 @@ }, 'doc': 'A webinar, conference talk, or other type of presentation.'}), - ('ou:conference', ('guid', {}), { + ('ou:conference', ('meta:activity', {}), { 'template': {'title': 'conference'}, 'interfaces': ( - ('ou:sponsored', {}), + ('meta:promoted', {}), + ('meta:attendable', {}), + ('meta:sponsorable', {}), ), 'display': { 'columns': ( @@ -223,10 +230,12 @@ # ), # 'doc': 'A hierarchical taxonomy of contest types.'}), - ('ou:contest', ('guid', {}), { + ('ou:contest', ('meta:activity', {}), { 'template': {'title': 'contest'}, 'interfaces': ( - ('ou:sponsored', {}), + ('meta:promoted', {}), + ('meta:attendable', {}), + ('meta:sponsorable', {}), ), 'doc': 'A competitive event resulting in a ranked set of participants.'}), diff --git a/synapse/models/person.py b/synapse/models/person.py index ec751315e3d..92311945b10 100644 --- a/synapse/models/person.py +++ b/synapse/models/person.py @@ -13,10 +13,10 @@ ), 'doc': 'An instance of an edu:course taught at a given time.'}), - ('ps:education', ('guid', {}), { + ('ps:education', ('entity:activity', {}), { 'display': { 'columns': ( - {'type': 'prop', 'opts': {'name': 'student::name'}}, + {'type': 'prop', 'opts': {'name': 'actor::name'}}, {'type': 'prop', 'opts': {'name': 'institution::name'}}, # TODO allow columns to use virtual props # {'type': 'prop', 'opts': {'name': 'period.min'}}, @@ -25,10 +25,10 @@ }, 'doc': 'A period of education for an individual.'}), - ('ps:achievement', ('guid', {}), { + ('ps:achievement', ('entity:event', {}), { 'display': { 'columns': ( - {'type': 'prop', 'opts': {'name': 'awardee::name'}}, + {'type': 'prop', 'opts': {'name': 'actor::name'}}, {'type': 'prop', 'opts': {'name': 'award::name'}}, {'type': 'prop', 'opts': {'name': 'award::org::name'}}, {'type': 'prop', 'opts': {'name': 'awarded'}}, @@ -45,12 +45,12 @@ ), 'doc': 'A person or persona.'}), - ('ps:workhist', ('guid', {}), { + ('ps:workhist', ('entity:activity', {}), { 'display': { 'columns': ( - {'type': 'prop', 'opts': {'name': 'contact::name'}}, + {'type': 'prop', 'opts': {'name': 'actor:name'}}, {'type': 'prop', 'opts': {'name': 'title'}}, - {'type': 'prop', 'opts': {'name': 'org:name'}}, + {'type': 'prop', 'opts': {'name': 'employer:name'}}, # TODO allow columns to use virtual props # {'type': 'prop', 'opts': {'name': 'period.min'}}, # {'type': 'prop', 'opts': {'name': 'period.max'}}, @@ -111,19 +111,17 @@ ('ps:workhist', {}, ( - ('contact', ('entity:individual', {}), { - 'doc': 'The contact which has the work history.'}), + ('employer', ('entity:actor', {}), { + 'prevnames': ('org',), + 'doc': 'The employer.'}), - ('org', ('ou:org', {}), { - 'doc': 'The org that this work history orgname refers to.'}), - - ('org:name', ('entity:name', {}), { + ('employer:name', ('entity:name', {}), { 'prevnames': ('orgname',), - 'doc': 'The reported name of the org the contact worked for.'}), + 'doc': 'The name of the employer.'}), - ('org:fqdn', ('inet:fqdn', {}), { + ('employer:fqdn', ('inet:fqdn', {}), { 'prevnames': ('orgfqdn',), - 'doc': 'The reported fqdn of the org the contact worked for.'}), + 'doc': 'The FQDN of the employer.'}), ('job:type', ('ou:job:type:taxonomy', {}), { 'doc': 'The type of job.', @@ -145,7 +143,7 @@ ('period', ('ival', {}), { 'prevnames': ('started', 'ended', 'duration'), - 'doc': 'The period of time that the contact worked for the organization.'}), + 'doc': 'The period of time that the actor worked for the employer.'}), ('desc', ('str', {}), { 'doc': 'A description of the work done as part of the job.'}), @@ -197,8 +195,8 @@ )), ('ps:education', {}, ( - ('student', ('entity:individual', {}), { - 'doc': 'The student who attended the educational institution.'}), + #('student', ('entity:individual', {}), { + #'doc': 'The student who attended the educational institution.'}), ('institution', ('ou:org', {}), { 'doc': 'The organization providing educational services.'}), @@ -213,14 +211,14 @@ )), ('ps:achievement', {}, ( - ('awardee', ('entity:individual', {}), { - 'doc': 'The recipient of the award.'}), + #('awardee', ('entity:individual', {}), { + #'doc': 'The recipient of the award.'}), ('award', ('ou:award', {}), { 'doc': 'The award bestowed on the awardee.'}), - ('awarded', ('time', {}), { - 'doc': 'The date the award was granted to the awardee.'}), + #('awarded', ('time', {}), { + #'doc': 'The date the award was granted to the awardee.'}), ('expires', ('time', {}), { 'doc': 'The date the award or certification expires.'}), diff --git a/synapse/models/risk.py b/synapse/models/risk.py index 5f5dbdc8bbc..1eea40a9c8f 100644 --- a/synapse/models/risk.py +++ b/synapse/models/risk.py @@ -104,19 +104,39 @@ async def _normPyStr(self, text, view=None): ), 'doc': 'A hierarchical taxonomy of threat statuses.'}), - ('risk:attack', ('guid', {}), { + ('risk:attack', ('entity:event', {}), { 'template': {'title': 'attack'}, 'interfaces': ( - ('entity:action', {}), ('meta:reported', {}), ), - 'doc': 'An instance of an actor attacking a target.'}), + 'props': ( + ('type', ('risk:attack:type:taxonomy', {}), { + 'ex': 'cno.phishing', + 'doc': 'A type for the attack, as a taxonomy entry.'}), - ('risk:attack:status:taxonomy', ('taxonomy', {}), { - 'interfaces': ( - ('meta:taxonomy', {}), + ('detected', ('time', {}), { + 'doc': 'The first confirmed detection time of the attack.'}), + + ('success', ('bool', {}), { + 'doc': 'Set if the attack was known to have succeeded or not.'}), + + # FIXME overfit + # ('campaign', ('entity:campaign', {}), { + # 'doc': 'Set if the attack was part of a larger campaign.'}), + + # ('compromise', ('risk:compromise', {}), { + # 'doc': 'A compromise that this attack contributed to.'}), + + ('severity', ('meta:score', {}), { + 'doc': 'A severity rank for the attack.'}), + + ('sophistication', ('meta:score', {}), { + 'doc': 'The assessed sophistication of the attack.'}), + + # ('prev', ('risk:attack', {}), { + # 'doc': 'The previous/parent attack in a list or hierarchy.'}), ), - 'doc': 'A hierarchical taxonomy of attack statuses.'}), + 'doc': 'An instance of an actor attacking a target.'}), ('risk:alert:type:taxonomy', ('taxonomy', {}), { 'interfaces': ( @@ -137,7 +157,7 @@ async def _normPyStr(self, text, view=None): 'template': {'title': 'compromise'}, 'interfaces': ( ('meta:reported', {}), - ('entity:action', {}), + #('entity:action', {}), ), 'display': { 'columns': ( @@ -237,7 +257,7 @@ async def _normPyStr(self, text, view=None): 'template': {'title': 'leak'}, 'interfaces': ( ('meta:reported', {}), - ('entity:action', {}), + #('entity:action', {}), ), 'display': { 'columns': ( @@ -265,7 +285,7 @@ async def _normPyStr(self, text, view=None): 'template': {'title': 'extortion'}, 'interfaces': ( ('meta:reported', {}), - ('entity:action', {}), + #('entity:action', {}), ), 'display': { 'columns': ( @@ -288,35 +308,40 @@ async def _normPyStr(self, text, view=None): 'interfaces': ( ('meta:taxonomy', {}), ), + 'props': (), 'doc': 'An outage cause taxonomy.'}), ('risk:outage:type:taxonomy', ('taxonomy', {}), { 'interfaces': ( ('meta:taxonomy', {}), ), + 'props': (), 'doc': 'An outage type taxonomy.'}), - ('risk:outage:status:taxonomy', ('taxonomy', {}), { - 'interfaces': ( - ('meta:taxonomy', {}), - ), - 'doc': 'An outage status taxonomy.'}), - - ('risk:outage', ('guid', {}), { + ('risk:outage', ('entity:affected', {}), { 'template': {'title': 'outage'}, 'interfaces': ( ('meta:reported', {}), ), 'display': { 'columns': ( - {'type': 'prop', 'opts': {'name': 'period'}}, {'type': 'prop', 'opts': {'name': 'name'}}, + {'type': 'prop', 'opts': {'name': 'period'}}, {'type': 'prop', 'opts': {'name': 'provider:name'}}, {'type': 'prop', 'opts': {'name': 'reporter:name'}}, {'type': 'prop', 'opts': {'name': 'cause'}}, {'type': 'prop', 'opts': {'name': 'type'}}, ), }, + 'props': ( + ('type', ('risk:outage:type:taxonomy', {}), { + 'ex': 'service.power', + 'doc': 'The type of outage.'}), + + ('cause', ('risk:outage:cause:taxonomy', {}), { + 'ex': 'nature.earthquake', + 'doc': 'The outage cause type.'}), + ), 'doc': 'An outage event which affected resource availability.'}), ('risk:extortion:type:taxonomy', ('taxonomy', {}), { @@ -362,14 +387,14 @@ async def _normPyStr(self, text, view=None): (('risk:extortion', 'leveraged', 'meta:observable'), { 'doc': 'The extortion event was based on attacker access to the target node.'}), - (('meta:event', 'caused', 'risk:outage'), { - 'doc': 'The event caused the outage.'}), + #(('meta:event', 'caused', 'risk:outage'), { + #'doc': 'The event caused the outage.'}), - (('risk:attack', 'caused', 'risk:alert'), { - 'doc': 'The attack caused the alert.'}), + #(('risk:attack', 'caused', 'risk:alert'), { + #'doc': 'The attack caused the alert.'}), - (('risk:attack', 'caused', 'risk:outage'), { - 'doc': 'The attack caused the outage.'}), + #(('risk:attack', 'caused', 'risk:outage'), { + #'doc': 'The attack caused the outage.'}), (('risk:outage', 'impacted', None), { 'doc': 'The outage event impacted the availability of the target node.'}), @@ -694,8 +719,8 @@ async def _normPyStr(self, text, view=None): 'ex': 'cno.phishing', 'doc': 'A type for the attack, as a taxonomy entry.'}), - ('time', ('time', {}), { - 'doc': 'Set if the time of the attack is known.'}), + # ('time', ('time', {}), { + # 'doc': 'Set if the time of the attack is known.'}), ('detected', ('time', {}), { 'doc': 'The first confirmed detection time of the attack.'}), @@ -704,11 +729,11 @@ async def _normPyStr(self, text, view=None): 'doc': 'Set if the attack was known to have succeeded or not.'}), # FIXME overfit - ('campaign', ('entity:campaign', {}), { - 'doc': 'Set if the attack was part of a larger campaign.'}), + # ('campaign', ('entity:campaign', {}), { + # 'doc': 'Set if the attack was part of a larger campaign.'}), - ('compromise', ('risk:compromise', {}), { - 'doc': 'A compromise that this attack contributed to.'}), + # ('compromise', ('risk:compromise', {}), { + # 'doc': 'A compromise that this attack contributed to.'}), ('severity', ('meta:score', {}), { 'doc': 'A severity rank for the attack.'}), @@ -716,8 +741,8 @@ async def _normPyStr(self, text, view=None): ('sophistication', ('meta:score', {}), { 'doc': 'The assessed sophistication of the attack.'}), - ('prev', ('risk:attack', {}), { - 'doc': 'The previous/parent attack in a list or hierarchy.'}), + # ('prev', ('risk:attack', {}), { + # 'doc': 'The previous/parent attack in a list or hierarchy.'}), )), @@ -760,13 +785,8 @@ async def _normPyStr(self, text, view=None): )), - ('risk:outage:type:taxonomy', {}, ()), - ('risk:outage:cause:taxonomy', {}, ()), ('risk:outage', {}, ( - ('period', ('ival', {}), { - 'doc': 'The time period where the outage impacted availability.'}), - ('type', ('risk:outage:type:taxonomy', {}), { 'ex': 'service.power', 'doc': 'The type of outage.'}), @@ -775,14 +795,15 @@ async def _normPyStr(self, text, view=None): 'ex': 'nature.earthquake', 'doc': 'The outage cause type.'}), - ('attack', ('risk:attack', {}), { - 'doc': 'An attack which caused the outage.'}), + #('attack', ('risk:attack', {}), { + #'doc': 'An attack which caused the outage.'}), - ('provider', ('ou:org', {}), { - 'doc': 'The organization which experienced the outage event.'}), + # :party / :party:name + # ('provider', ('ou:org', {}), { + # 'doc': 'The organization which experienced the outage event.'}), - ('provider:name', ('entity:name', {}), { - 'doc': 'The name of the organization which experienced the outage event.'}), + # ('provider:name', ('entity:name', {}), { + # 'doc': 'The name of the organization which experienced the outage event.'}), )), ('risk:extortion:type:taxonomy', {}, ()), @@ -797,8 +818,9 @@ async def _normPyStr(self, text, view=None): ('type', ('risk:extortion:type:taxonomy', {}), { 'doc': 'A type taxonomy for the extortion event.'}), - ('target', ('entity:actor', {}), { - 'doc': 'The extortion target identity.'}), + # :party / :party:name + # ('target', ('entity:actor', {}), { + # 'doc': 'The extortion target identity.'}), ('success', ('bool', {}), { 'doc': "Set to true if the victim met the attacker's demands."}), @@ -812,8 +834,9 @@ async def _normPyStr(self, text, view=None): ('public:url', ('inet:url', {}), { 'doc': 'The URL where the attacker publicly announced the extortion.'}), - ('compromise', ('risk:compromise', {}), { - 'doc': 'The compromise which allowed the attacker to extort the target.'}), + # compromise -(leadto)> + # ('compromise', ('risk:compromise', {}), { + # 'doc': 'The compromise which allowed the attacker to extort the target.'}), ('demanded:payment:price', ('econ:price', {}), { 'doc': 'The payment price which was demanded.'}), diff --git a/synapse/models/transport.py b/synapse/models/transport.py index b74e31b070b..a1fddee0491 100644 --- a/synapse/models/transport.py +++ b/synapse/models/transport.py @@ -25,7 +25,7 @@ ('transport:vehicle', ('ndef', {'interface': 'transport:vehicle'}), { 'doc': 'A vehicle such as an aircraft or sea vessel.'}), - ('transport:occupant', ('guid', {}), { + ('transport:occupant', ('entity:activity', {}), { 'doc': 'An occupant of a vehicle on a trip.'}), ('transport:occupant:role:taxonomy', ('taxonomy', {}), { @@ -542,8 +542,8 @@ ('role', ('transport:occupant:role:taxonomy', {}), { 'doc': 'The role of the occupant such as captain, crew, passenger.'}), - ('contact', ('entity:individual', {}), { - 'doc': 'Contact information of the occupant.'}), + #('contact', ('entity:individual', {}), { + #'doc': 'Contact information of the occupant.'}), ('trip', ('transport:trip', {}), { 'doc': 'The trip, such as a flight or train ride, being taken by the occupant.'}), @@ -555,6 +555,7 @@ 'doc': 'The seat which the occupant sat in. Likely in a vehicle specific format.'}), ('period', ('ival', {}), { + # keeping for prevnames... 'prevnames': ('boarded', 'disembarked'), 'doc': 'The period when the occupant was aboard the vehicle.'}), From ff5a36cc1720714d64798f872261c022da4c512a Mon Sep 17 00:00:00 2001 From: visi Date: Tue, 3 Feb 2026 15:47:58 -0500 Subject: [PATCH 03/25] wip --- synapse/models/entity.py | 2 +- synapse/models/risk.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/synapse/models/entity.py b/synapse/models/entity.py index 3ca0a3b6c71..b33e591dff7 100644 --- a/synapse/models/entity.py +++ b/synapse/models/entity.py @@ -19,7 +19,7 @@ 'doc': 'The roles of the actor in the {title}.'}), ), - 'doc': 'Properties common to actions taken by entities.'}), + 'doc': 'Properties common to actions taken by an individual actor.'}), # ('entity:affected', { # 'template': {'affected': 'affected'}, diff --git a/synapse/models/risk.py b/synapse/models/risk.py index 1eea40a9c8f..9a623cf9e68 100644 --- a/synapse/models/risk.py +++ b/synapse/models/risk.py @@ -110,6 +110,7 @@ async def _normPyStr(self, text, view=None): ('meta:reported', {}), ), 'props': ( + ('type', ('risk:attack:type:taxonomy', {}), { 'ex': 'cno.phishing', 'doc': 'A type for the attack, as a taxonomy entry.'}), @@ -157,7 +158,6 @@ async def _normPyStr(self, text, view=None): 'template': {'title': 'compromise'}, 'interfaces': ( ('meta:reported', {}), - #('entity:action', {}), ), 'display': { 'columns': ( @@ -667,18 +667,19 @@ async def _normPyStr(self, text, view=None): ('vector', ('risk:attack', {}), { 'doc': 'The attack assessed to be the initial compromise vector.'}), - ('target', ('entity:actor', {}), { - 'doc': 'Contact information representing the target.'}), + #('target', ('entity:actor', {}), { + #'doc': 'Contact information representing the target.'}), ('period', ('ival', {}), { 'doc': 'The period over which the target was compromised.'}), # FIXME - is this overfit being one-to-one? - ('campaign', ('entity:campaign', {}), { - 'doc': 'The campaign that this compromise is part of.'}), + #('campaign', ('entity:campaign', {}), { + #'doc': 'The campaign that this compromise is part of.'}), - ('detected', ('time', {}), { - 'doc': 'The first confirmed detection time of the compromise.'}), + # Is this the same as enetity:discovered? + # ('detected', ('time', {}), { + # 'doc': 'The first confirmed detection time of the compromise.'}), ('loss:pii', ('int', {}), { 'doc': 'The number of records compromised which contain PII.'}), From aa31ad3cb1631b191f299ccacbef3464f00340b7 Mon Sep 17 00:00:00 2001 From: visi Date: Wed, 4 Feb 2026 09:54:53 -0500 Subject: [PATCH 04/25] wip --- synapse/common.py | 2 +- synapse/datamodel.py | 32 ++++++++-- synapse/models/entity.py | 130 ++++++++++++++++++++++----------------- synapse/models/orgs.py | 3 +- synapse/models/person.py | 2 +- synapse/models/risk.py | 15 ++++- 6 files changed, 116 insertions(+), 68 deletions(-) diff --git a/synapse/common.py b/synapse/common.py index b307a015ecf..72ec479bf71 100644 --- a/synapse/common.py +++ b/synapse/common.py @@ -524,7 +524,7 @@ def yamlload(*paths): with io.open(path, 'rb') as fd: return yamlloads(fd) -def yamldump(obj, stream: typing.Optional[typing.BinaryIO] =None) -> bytes: +def yamldump(obj, stream=None): ''' Dump a object to yaml. diff --git a/synapse/datamodel.py b/synapse/datamodel.py index fccd66a5dbf..a845ea292c3 100644 --- a/synapse/datamodel.py +++ b/synapse/datamodel.py @@ -973,9 +973,29 @@ def addDataModels(self, mods): ctors[name] = (name, ctor, opts, info) # load all the types in order... + typetodo = {} for _, mdef in mods: - for typename, (basename, typeopts), typeinfo in mdef.get('types', ()): - self.addType(typename, basename, typeopts, typeinfo, skipinit=True) + for typename, basetype, typeopts in mdef.get('types', ()): + typetodo[typename] = (basetype, typeopts) + + def _addType(typename, basetype, typeinfo): + + if self.types.get(typename) is not None: + return + + # see if we can resolve our base type if it's not loaded yet + if self.types.get(basetype[0]) is None: + todo = typetodo.get(basetype[0]) + if todo is None: + mesg = 'No such base type {basetype[0] for type {typename}.' + raise s_exc.NoSuchType(mesg=mesg) + + _addType(basetype[0], todo[0], todo[1]) + + self.addType(typename, basetype[0], basetype[1], typeinfo, skipinit=True) + + for (typename, (basetype, typeinfo)) in typetodo.items(): + _addType(typename, basetype, typeinfo) # finish initializing types for name, tobj in self.types.items(): @@ -1061,6 +1081,7 @@ def _getFormsMaybeIface(self, name): def addEdge(self, edgetype, edgeinfo): + print(edgetype) n1form, verb, n2form = edgetype if not isinstance(verb, str): @@ -1130,7 +1151,8 @@ def addType(self, typename, basename, typeopts, typeinfo, skipinit=False): base = self.types.get(basename) if base is None: - raise s_exc.NoSuchType(name=basename) + mesg = f'No such base type: {basename} for type {typename}.' + raise s_exc.NoSuchType(mesg=mesg, name=basename) newtype = base.extend(typename, typeopts, typeinfo, skipinit=skipinit) @@ -1178,6 +1200,7 @@ def mergeVirts(self, v0, v1): def addForm(self, formname, forminfo, propdefs, checks=True): + print(f'{formname} {forminfo}') if not s_grammar.isFormName(formname): mesg = f'Invalid form name {formname}' raise s_exc.BadFormDef(name=formname, mesg=mesg) @@ -1369,7 +1392,8 @@ def addIface(self, name, info): self.ifaces[name] = info # FIXME polyprops - self.addType(name, 'ndef', {'interface': name}, {'doc': 'FIXME POLYPROP PLACE HOLDER'}) + if self.types.get(name) is None: + self.addType(name, 'ndef', {'interface': name}, {'doc': 'FIXME POLYPROP PLACE HOLDER'}) def reqTypeNotInUse(self, typename): if self.propsbytype.get(typename): diff --git a/synapse/models/entity.py b/synapse/models/entity.py index b33e591dff7..6e901266e9a 100644 --- a/synapse/models/entity.py +++ b/synapse/models/entity.py @@ -21,6 +21,16 @@ ), 'doc': 'Properties common to actions taken by an individual actor.'}), + ('entity:affected', { + 'props': ( + ('party', ('entity:actor', {}), { + 'doc': 'The party which was affected.'}), + + ('party:name', ('entity:name', {}), { + 'doc': 'The name of the party which was affected.'}), + ), + 'doc': 'Properties common to affected entities.'}), + # ('entity:affected', { # 'template': {'affected': 'affected'}, # 'props': ( @@ -224,6 +234,18 @@ ('entity:contactlist', ('guid', {}), { 'doc': 'A list of contacts.'}), + ('entity:event', ('meta:event', {}), { + 'interfaces': ( + ('entity:action', {}), + ), + 'doc': 'An event carried out by an actor.'}), + + ('entity:activity', ('meta:activity', {}), { + 'interfaces': ( + ('entity:action', {}), + ), + 'doc': 'Activity carried out by an actor.'}), + ('entity:relationship:type:taxonomy', ('taxonomy', {}), { 'interfaces': ( ('meta:taxonomy', {}), @@ -318,43 +340,35 @@ 'doc': 'Represents a conflict where two or more actors have mutually exclusive goals.'}), # TODO - belief:subscriber= - ('entity:event', ('meta:event', {}), { - 'interfaces': ( - ('entity:action', {}), - ), - 'doc': 'An event carried out by an actor.'}), - - ('entity:activity', ('meta:activity', {}), { - 'interfaces': ( - ('entity:action', {}), - ), - 'doc': 'Activity carried out by an actor.'}), - ('entity:affected', ('meta:activity', {}), { - 'props': ( - ('party', ('entity:actor', {}), { - 'doc': 'The party which was affected.'}), + # ('entity:affected', ('meta:activity', {}), { + # 'props': ( + # ('party', ('entity:actor', {}), { + # 'doc': 'The party which was affected.'}), - ('party:name', ('entity:name', {}), { - 'doc': 'The name of the party which was affected.'}), - ), - 'doc': 'An entity which was affected by events.'}), + # ('party:name', ('entity:name', {}), { + # 'doc': 'The name of the party which was affected.'}), + # ), + # 'doc': 'An entity which was affected by events.'}), # entity:knew / entity:awareof? - ('entity:observed', ('entity:affected', {}), { - 'props': ( - ('event', ('meta:causal', {}), { - 'doc': 'The event which was observed by the entity.'}), - ), - 'doc': 'Passive observation of an event by an entity.'}), + # ('entity:observed', ('entity:affected', {}), { + # 'interfaces': ( + # ('entity:affected', {}), + # ), + # 'props': ( + # ('event', ('meta:causal', {}), { + # 'doc': 'The event which was observed by the entity.'}), + # ), + # 'doc': 'Passive observation of an event by an entity.'}), ('entity:involved', ('entity:activity', {}), { 'props': ( ('event', ('meta:causal', {}), { 'doc': 'The event or activity the actor was involved in.'}), ), - 'doc': "Represents an actor's active involvement with an event."}) + 'doc': "Represents an actor's active involvement with an event."}), ('entity:support', ('entity:involved', {}), { 'template': {'title': 'support'}, @@ -500,8 +514,8 @@ 'doc': 'A description of the goal.'}), )), - ('entity:campaign:type:taxonomy', { - 'prevnames': ('ou:camptype',)}, ()), + #('entity:campaign:type:taxonomy', { + #'prevnames': ('ou:camptype',)}, ()), ('entity:campaign', {}, ( @@ -597,19 +611,19 @@ # 'doc': 'The action which the actor {supported}.'}), # )), - ('entity:contribution', ('entity:activity', {}), { - 'props': ( + # ('entity:contribution', ('entity:activity', {}), { + # 'props': ( - ('event', ('meta:causal', {}), { - 'doc': 'The activity supported by the actor.'}), + # ('event', ('meta:causal', {}), { + # 'doc': 'The activity supported by the actor.'}), - ('value', ('econ:price', {}), { - 'doc': 'The assessed value of the contribution.'}), + # ('value', ('econ:price', {}), { + # 'doc': 'The assessed value of the contribution.'}), - ('currency', ('econ:currency', {}), { - 'doc': 'The currency used for the assessed value.'}), - ), - 'doc': 'An instance of an entity contributing to an event.'}), + # ('currency', ('econ:currency', {}), { + # 'doc': 'The currency used for the assessed value.'}), + # ), + # 'doc': 'An instance of an entity contributing to an event.'}), # ('entity:participated', ('meta:activity', {}), { # 'props': ( @@ -618,29 +632,29 @@ # ), # 'doc': 'An instance of an entity actively participating in an event.'}), - ('entity:sponsored', ('entity:activity', {}), { - 'props': ( - ('event', ('meta:sponsorable', {}), { - 'doc': 'The event which was sponsored by the actor.'}), + # ('entity:sponsored', ('entity:activity', {}), { + # 'props': ( + # ('event', ('meta:sponsorable', {}), { + # 'doc': 'The event which was sponsored by the actor.'}), - ('value', ('econ:price', {}), { - 'doc': 'The assessed value of the contribution.'}), - ), - 'doc': 'An instance of an actor sponsoring an event.'}), + # ('value', ('econ:price', {}), { + # 'doc': 'The assessed value of the contribution.'}), + # ), + # 'doc': 'An instance of an actor sponsoring an event.'}), - ('entity:attended', ('entity:activity', {}), { - 'props': ( - ('event', ('meta:attendable', {}), { - 'doc': 'The event which the actor attended.'}), - ), - 'doc': 'An intance of an entity attending an organized event.'}), + # ('entity:attended', ('entity:activity', {}), { + # 'props': ( + # ('event', ('meta:attendable', {}), { + # 'doc': 'The event which the actor attended.'}), + # ), + # 'doc': 'An intance of an entity attending an organized event.'}), - ('entity:registered', ('entity:event', {}), { - 'props': ( - ('event', ('meta:attendable', {}), { - 'doc': 'The event which the actor registered attended.'}), - ), - 'doc': 'An instance of an entity registering for an organized event.'}), + # ('entity:registered', ('entity:event', {}), { + # 'props': ( + # ('event', ('meta:attendable', {}), { + # 'doc': 'The event which the actor registered attended.'}), + # ), + # 'doc': 'An instance of an entity registering for an organized event.'}), ), }), diff --git a/synapse/models/orgs.py b/synapse/models/orgs.py index 71dfe3c3d48..4d41fd7aa0a 100644 --- a/synapse/models/orgs.py +++ b/synapse/models/orgs.py @@ -166,8 +166,7 @@ ), 'doc': 'A meeting.'}), - ('ou:presentation', ('meta:activity', {}), { - 'prevnames': ('ou:preso',), + ('ou:preso', ('meta:activity', {}), { 'template': {'title': 'presentation'}, 'interfaces': ( ('meta:promoted', {}), diff --git a/synapse/models/person.py b/synapse/models/person.py index 92311945b10..3602369dfd5 100644 --- a/synapse/models/person.py +++ b/synapse/models/person.py @@ -9,7 +9,7 @@ ('edu:class', ('guid', {}), { 'interfaces': ( - ('ou:attendable', {'template': {'title': 'class'}}), + ('meta:attendable', {'template': {'title': 'class'}}), ), 'doc': 'An instance of an edu:course taught at a given time.'}), diff --git a/synapse/models/risk.py b/synapse/models/risk.py index 9a623cf9e68..83b4e9240c5 100644 --- a/synapse/models/risk.py +++ b/synapse/models/risk.py @@ -154,10 +154,11 @@ async def _normPyStr(self, text, view=None): ), 'doc': 'A taxonomy of compromise statuses.'}), - ('risk:compromise', ('guid', {}), { + ('risk:compromise', ('meta:activity', {}), { 'template': {'title': 'compromise'}, 'interfaces': ( ('meta:reported', {}), + ('risk:victimized', {}), ), 'display': { 'columns': ( @@ -298,6 +299,10 @@ async def _normPyStr(self, text, view=None): }, 'doc': 'An event where an attacker attempted to extort a victim.'}), + #('risk:demanded', ('entity:event', {}), { + #('risk:threatened' + #('risk:theft + ('risk:extortion:status:taxonomy', ('taxonomy', {}), { 'interfaces': ( ('meta:taxonomy', {}), @@ -318,10 +323,11 @@ async def _normPyStr(self, text, view=None): 'props': (), 'doc': 'An outage type taxonomy.'}), - ('risk:outage', ('entity:affected', {}), { + ('risk:outage', ('meta:activity', {}), { 'template': {'title': 'outage'}, 'interfaces': ( ('meta:reported', {}), + #('entity:affected', {}), ), 'display': { 'columns': ( @@ -355,6 +361,11 @@ async def _normPyStr(self, text, view=None): ), 'interfaces': ( + ('risk:victimized', { + 'interfaces': ( + ('entity:affected', {}), + ), + }), ('risk:mitigatable', { 'doc': 'A common interface for risks which may be mitigated.', }), From ab4784e8376c0a19c39c0cea3952f17c67f24533 Mon Sep 17 00:00:00 2001 From: visi Date: Fri, 6 Feb 2026 11:29:02 -0500 Subject: [PATCH 05/25] wip --- synapse/models/base.py | 92 ++++++++++------------ synapse/models/biz.py | 31 ++++++++ synapse/models/entity.py | 164 ++++++++++++++++++++++----------------- synapse/models/orgs.py | 3 +- synapse/models/person.py | 2 +- synapse/models/risk.py | 143 +++++++++++++++------------------- 6 files changed, 230 insertions(+), 205 deletions(-) diff --git a/synapse/models/base.py b/synapse/models/base.py index d7f47bef6b6..4cd964fe962 100644 --- a/synapse/models/base.py +++ b/synapse/models/base.py @@ -77,38 +77,57 @@ ), 'doc': 'A hierarchical taxonomy of timeline types.'}), - ('meta:event', ('guid', {}), { - 'template': {'title': 'event'}, - 'interfaces': ( - ('meta:causal', {}), - ), - 'props': ( - - ('time', ('time', {}), { - 'doc': 'The time that the {title} occured.'}), - - ('type', ('meta:event:type:taxonomy', {}), { - 'doc': 'The type of event.'}), - ), - 'doc': 'An analytically relevant event.'}), - ('meta:activity', ('guid', {}), { 'template': {'title': 'activity'}, 'interfaces': ( ('meta:causal', {}), ), 'props': ( + ('name', ('base:name', {}), { + 'doc': 'The name of the {title}.'}), + + ('desc', ('text', {}), { + 'doc': 'A description of the {title}.'}), + ('period', ('time', {}), { - 'doc': 'The period over which the {activity} occured.'}), + 'doc': 'The period over which the {title} occured.'}), + + ('activity', ('meta:activity', {}), { + 'doc': 'A parent activity which includes this {title}.'}), ), 'doc': 'Analytically relevant activity.'}), ('meta:event:type:taxonomy', ('taxonomy', {}), { + 'prevnames': ('meta:event:taxonomy',), 'interfaces': ( ('meta:taxonomy', {}), ), + 'props': (), 'doc': 'A hierarchical taxonomy of event types.'}), + ('meta:event', ('guid', {}), { + 'template': {'title': 'event'}, + 'interfaces': ( + ('meta:causal', {}), + ), + 'props': ( + ('name', ('base:name', {}), { + 'doc': 'The name of the {title}.'}), + + ('desc', ('text', {}), { + 'doc': 'A description of the {title}.'}), + + ('activity', ('meta:activity', {}), { + 'doc': 'A parent activity which includes this {title}.'}), + + ('time', ('time', {}), { + 'doc': 'The time that the {title} occured.'}), + + ('type', ('meta:event:type:taxonomy', {}), { + 'doc': 'The type of event.'}), + ), + 'doc': 'An analytically relevant event.'}), + ('meta:ruleset:type:taxonomy', ('taxonomy', {}), { 'interfaces': ( ('meta:taxonomy', {}), @@ -254,21 +273,21 @@ }, 'props': ( - ('id', ('meta:id', {}), { + ('id', ('base:id', {}), { 'alts': ('ids',), 'doc': 'A unique ID given to the {title}.'}), - ('ids', ('array', {'type': 'meta:id'}), { + ('ids', ('array', {'type': 'base:id'}), { 'doc': 'An array of alternate IDs given to the {title}.'}), ('url', ('inet:url', {}), { 'doc': 'The URL for the {title}.'}), - ('name', ('meta:name', {}), { + ('name', ('base:name', {}), { 'alts': ('names',), 'doc': 'The primary name of the {title}.'}), - ('names', ('array', {'type': 'meta:name'}), { + ('names', ('array', {'type': 'base:name'}), { 'doc': 'A list of alternate names for the {title}.'}), ('desc', ('text', {}), { @@ -327,14 +346,7 @@ }), ('meta:causal', { - 'props': ( - ('name', ('base:name', {}), { - 'doc': 'The name of the {title}.'}), - - ('desc', ('text', {}), { - 'doc': 'A description of the {title}.'}), - ), - 'doc': 'Properties common to events and activity.'}), + 'doc': 'Implemented by events and activity which can lead to effects.'}), ('meta:usable', { 'template': {'title': 'item'}, @@ -525,30 +537,6 @@ ('meta:timeline:type:taxonomy', { 'prevnames': ('meta:timeline:taxonomy',)}, ()), - # ('meta:event', {}, ( - - # # FIXME discuss instant vs activity - # #('period', ('ival', {}), { - # #'doc': 'The period over which the {title} occurred.'}), - - # # FIXME redundant with :name / :names and should be removed - # # ('title', ('str', {}), { - # # 'doc': 'A title for the event.'}), - - # ('desc', ('text', {}), { - # 'doc': 'A description of the event.'}), - - # # FIXME conscious decision to fold all "event" types into one taxonomy - # ('type', ('meta:event:type:taxonomy', {}), { - # 'doc': 'Type of event.'}), - - # #('parent', ('meta:event', {}), { - # #'doc': 'The parent event.'}), - # )), - - ('meta:event:type:taxonomy', { - 'prevnames': ('meta:event:taxonomy',)}, ()), - ('meta:ruleset', {}, ( ('name', ('base:id', {}), { diff --git a/synapse/models/biz.py b/synapse/models/biz.py index 474675acfac..ddecbbc7172 100644 --- a/synapse/models/biz.py +++ b/synapse/models/biz.py @@ -54,6 +54,37 @@ ('meta:taxonomy', {}), ), 'doc': 'A hierarchical taxonomy of product types.'}), + + ('biz:asked', ('entity:event', {}), { + 'template': {'title': 'ask'}, + 'doc': 'An event where an actor made an ask as part of a negotiation.'}), + + ('biz:offered', ('entity:event', {}), { + 'template': {'title': 'offer'}, + 'doc': 'An event where an actor made an offer as part of a negotiation.'}), + ), + + 'interfaces': ( + + ('biz:negotiable', { + # TODO restrict to being implemented on meta:activity sub-forms + 'doc': 'An interface implemented by activities which involve negotiation.'}), + + ('biz:position', { + 'template': {'title': 'position'}, + 'props': ( + ('price', ('econ:price', {}), { + 'doc': 'The total price of the {title}.'}), + + ('expires', ('time', {}), { + 'doc': 'The time that the {title} expires.'}), + + ('activity', ('biz:negotiable', {}), { + 'doc': 'The negotiation that prompted the {title}.'}), + ), + # :via=? + # -(used)> meta:comms (interface for all quanta of comms?) + 'doc': 'An interface implemented by actors taking a position during a negotiation.'}), ), 'edges': ( diff --git a/synapse/models/entity.py b/synapse/models/entity.py index 6e901266e9a..b8bb3522d33 100644 --- a/synapse/models/entity.py +++ b/synapse/models/entity.py @@ -231,6 +231,25 @@ ), 'doc': 'Historical contact information about another contact.'}), + ('entity:alliance', ('guid', {}), { + 'template': {'title': 'alliance'}, + 'interfaces': ( + ('entity:actor', {}), + ('meta:reported', {}), + ), + 'props': ( + ('name', ('entity:name', {}), { + 'alts': ('names',), + 'doc': 'The primary name of the {title}.'}), + + ('names', ('array', {'type': 'entity:name'}), { + 'doc': 'A list of alternate names for the {title}.'}), + + ('members', ('array', {'interface': 'entity:actor'}), { + 'doc': 'The actors who are working together.'}), + ), + 'doc': 'An alliance of otherwise distinct actors working together.'}), + ('entity:contactlist', ('guid', {}), { 'doc': 'A list of contacts.'}), @@ -335,7 +354,7 @@ ('entity:conflict', ('meta:activity', {}), { 'props': ( ('adversaries', ('array', {'type': 'entity:actor'}), { - 'doc': 'The primary adversaries in conflict with one another.'}), + 'doc': 'The primary adversaries in conflict.'}), ), 'doc': 'Represents a conflict where two or more actors have mutually exclusive goals.'}), @@ -566,96 +585,101 @@ 'doc': 'The tag used to annotate nodes that are associated with the campaign.'}), )), - # ('entity:conflict', {}, ( + # Something must occur in time to be causal... + # (meta:causal) - An interface implemented by nodes which are causal. + # -(leadto)> - # ('name', ('meta:name', {}), { - # 'doc': 'The name of the conflict.'}), + # meta:event= (meta:causal) + # :time=